diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9080453e..fe58568a 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,6 +15,13 @@ "dotnet-csharpier" ], "rollForward": false + }, + "husky": { + "version": "0.7.1", + "commands": [ + "husky" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index bfd1b76d..4392d506 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,10 +3,19 @@ # top-most EditorConfig file root = true -# Don't use tabs for indentation. [*] +# Non-configurable behaviors +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# Configurable behaviors +# end_of_line = lf - there is no 'auto' with a .editorconfig indent_style = space -# (Please don't specify an indent_size here; that has too many unintended consequences.) +indent_size = 4 +max_line_length = 120 # Code files [*.{cs,csx,vb,vbx}] @@ -204,4 +213,4 @@ csharp_space_between_square_brackets = false # Blocks are allowed csharp_prefer_braces = true:silent csharp_preserve_single_line_blocks = true -csharp_preserve_single_line_statements = true \ No newline at end of file +csharp_preserve_single_line_statements = true diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..fd85d235 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,22 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +## husky task runner examples ------------------- +## Note : for local installation use 'dotnet' prefix. e.g. 'dotnet husky' + +## run all tasks +#husky run + +### run all tasks with group: 'group-name' +#husky run --group group-name + +## run task with name: 'task-name' +#husky run --name task-name + +## pass hook arguments to task +#husky run --args "$1" "$2" + +## or put your custom commands ------------------- +#echo 'Husky.Net is awesome!' + +dotnet husky run diff --git a/.husky/task-runner.json b/.husky/task-runner.json new file mode 100644 index 00000000..542f94fe --- /dev/null +++ b/.husky/task-runner.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://alirezanet.github.io/Husky.Net/schema.json", + "tasks": [ + { + "name": "Run csharpier", + "command": "dotnet", + "args": ["csharpier", "${staged}"], + "include": ["**/*.cs"] + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index bce5e1a4..b6839418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 2.2.0 - September 8, 2024 +## [2.2.0] - September 8, 2024 - DocumentFormat.OpenXml 3.0.2 -> 3.1.0 - DocumentFormat.OpenXml.Framework 3.0.2 -> 3.1.0 diff --git a/Clippit.Tests/Common/ChartUpdaterTests.cs b/Clippit.Tests/Common/ChartUpdaterTests.cs index 1197866d..764e618c 100644 --- a/Clippit.Tests/Common/ChartUpdaterTests.cs +++ b/Clippit.Tests/Common/ChartUpdaterTests.cs @@ -16,10 +16,9 @@ namespace Clippit.Tests.Common { public class ChartUpdaterTests : TestsBase { - public ChartUpdaterTests(ITestOutputHelper log) : base(log) - { - } - + public ChartUpdaterTests(ITestOutputHelper log) + : base(log) { } + [Theory] [InlineData("CU001-Chart-Cached-Data-01.docx")] [InlineData("CU002-Chart-Cached-Data-02.docx")] @@ -29,7 +28,6 @@ public ChartUpdaterTests(ITestOutputHelper log) : base(log) [InlineData("CU006-Chart-Cached-Data-06.docx")] [InlineData("CU007-Chart-Cached-Data-07.docx")] [InlineData("CU008-Chart-Cached-Data-08.docx")] - [InlineData("CU009-Chart-Embedded-Xlsx-01.docx")] [InlineData("CU010-Chart-Embedded-Xlsx-02.docx")] [InlineData("CU011-Chart-Embedded-Xlsx-03.docx")] @@ -39,10 +37,8 @@ public ChartUpdaterTests(ITestOutputHelper log) : base(log) [InlineData("CU015-Chart-Embedded-Xlsx-07.docx")] [InlineData("CU016-Chart-Embedded-Xlsx-08.docx")] [InlineData("CU017-Chart-Embedded-Xlsx-10.docx")] - [InlineData("CU018-Chart-Cached-Data-41.pptx")] [InlineData("CU019-Chart-Embedded-Xlsx-41.pptx")] - public void CU001(string name) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); @@ -52,109 +48,61 @@ public void CU001(string name) { var wmlTemplate = new WmlDocument(templateFile.FullName); - var afterUpdatingDocx = new FileInfo(Path.Combine(TempDir, templateFile.Name.Replace(".docx", "-processed-by-ChartUpdater.docx"))); + var afterUpdatingDocx = new FileInfo( + Path.Combine(TempDir, templateFile.Name.Replace(".docx", "-processed-by-ChartUpdater.docx")) + ); wmlTemplate.SaveAs(afterUpdatingDocx.FullName); using var wDoc = WordprocessingDocument.Open(afterUpdatingDocx.FullName, true); var chart1Data = new ChartData { - SeriesNames = new[] { - "Car", - "Truck", - "Van", - "Bike", - "Boat", - }, + SeriesNames = new[] { "Car", "Truck", "Van", "Bike", "Boat" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Q1", - "Q2", - "Q3", - "Q4", - }, + CategoryNames = new[] { "Q1", "Q2", "Q3", "Q4" }, Values = new[] { - new double[] { - 100, 310, 220, 450, - }, - new double[] { - 200, 300, 350, 411, - }, - new double[] { - 80, 120, 140, 600, - }, - new double[] { - 120, 100, 140, 400, - }, - new double[] { - 200, 210, 210, 480, - }, + new double[] { 100, 310, 220, 450 }, + new double[] { 200, 300, 350, 411 }, + new double[] { 80, 120, 140, 600 }, + new double[] { 120, 100, 140, 400 }, + new double[] { 200, 210, 210, 480 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart1", chart1Data); var chart2Data = new ChartData { - SeriesNames = new[] { - "Series" - }, + SeriesNames = new[] { "Series" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Cars", - "Trucks", - "Vans", - "Boats", - }, - Values = new[] - { - new double[] { - 320, 112, 64, 80, - }, - }, + CategoryNames = new[] { "Cars", "Trucks", "Vans", "Boats" }, + Values = new[] { new double[] { 320, 112, 64, 80 } }, }; ChartUpdater.UpdateChart(wDoc, "Chart2", chart2Data); var chart3Data = new ChartData { - SeriesNames = new[] { - "X1", - "X2", - "X3", - "X4", - "X5", - "X6", - }, + SeriesNames = new[] { "X1", "X2", "X3", "X4", "X5", "X6" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Y1", - "Y2", - "Y3", - "Y4", - "Y5", - "Y6", - }, + CategoryNames = new[] { "Y1", "Y2", "Y3", "Y4", "Y5", "Y6" }, Values = new[] { - new[] { 3.0, 2.1, .7, .7, 2.1, 3.0, }, - new[] { 3.0, 2.1, .8, .8, 2.1, 3.0, }, - new[] { 3.0, 2.4, 1.2, 1.2, 2.4, 3.0, }, - new[] { 3.0, 2.7, 1.7, 1.7, 2.7, 3.0, }, - new[] { 3.0, 2.9, 2.5, 2.5, 2.9, 3.0, }, - new[] { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, }, + new[] { 3.0, 2.1, .7, .7, 2.1, 3.0 }, + new[] { 3.0, 2.1, .8, .8, 2.1, 3.0 }, + new[] { 3.0, 2.4, 1.2, 1.2, 2.4, 3.0 }, + new[] { 3.0, 2.7, 1.7, 1.7, 2.7, 3.0 }, + new[] { 3.0, 2.9, 2.5, 2.5, 2.9, 3.0 }, + new[] { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart3", chart3Data); var chart4Data = new ChartData { - SeriesNames = new[] { - "Car", - "Truck", - "Van", - }, + SeriesNames = new[] { "Car", "Truck", "Van" }, CategoryDataType = ChartDataType.DateTime, CategoryFormatCode = 14, - CategoryNames = new[] { + CategoryNames = new[] + { ToExcelInteger(new DateTime(2013, 9, 1)), ToExcelInteger(new DateTime(2013, 9, 2)), ToExcelInteger(new DateTime(2013, 9, 3)), @@ -178,15 +126,9 @@ public void CU001(string name) }, Values = new[] { - new double[] { - 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 8, 8, 9, - }, - new double[] { - 2, 3, 3, 4, 4, 5, 6, 7, 8, 7, 8, 9, 9, 9, 7, 8, 9, 9, 10, 11, - }, - new double[] { - 2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 3, 4, 5, 5, 4, - }, + new double[] { 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 8, 8, 9 }, + new double[] { 2, 3, 3, 4, 4, 5, 6, 7, 8, 7, 8, 9, 9, 9, 7, 8, 9, 9, 10, 11 }, + new double[] { 2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 3, 4, 5, 5, 4 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart4", chart4Data); @@ -195,35 +137,22 @@ public void CU001(string name) { var pmlTemplate = new PmlDocument(templateFile.FullName); - var afterUpdatingPptx = new FileInfo(Path.Combine(TempDir, templateFile.Name.Replace(".pptx", "-processed-by-ChartUpdater.pptx"))); + var afterUpdatingPptx = new FileInfo( + Path.Combine(TempDir, templateFile.Name.Replace(".pptx", "-processed-by-ChartUpdater.pptx")) + ); pmlTemplate.SaveAs(afterUpdatingPptx.FullName); using var pDoc = PresentationDocument.Open(afterUpdatingPptx.FullName, true); var chart1Data = new ChartData { - SeriesNames = new[] { - "Car", - "Truck", - "Van", - }, + SeriesNames = new[] { "Car", "Truck", "Van" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Q1", - "Q2", - "Q3", - "Q4", - }, + CategoryNames = new[] { "Q1", "Q2", "Q3", "Q4" }, Values = new[] { - new double[] { - 320, 310, 320, 330, - }, - new double[] { - 201, 224, 230, 221, - }, - new double[] { - 180, 200, 220, 230, - }, + new double[] { 320, 310, 320, 330 }, + new double[] { 201, 224, 230, 221 }, + new double[] { 180, 200, 220, 230 }, }, }; ChartUpdater.UpdateChart(pDoc, 1, chart1Data); diff --git a/Clippit.Tests/Common/MetricsGetterTests.cs b/Clippit.Tests/Common/MetricsGetterTests.cs index 63f8d89d..2472094d 100644 --- a/Clippit.Tests/Common/MetricsGetterTests.cs +++ b/Clippit.Tests/Common/MetricsGetterTests.cs @@ -15,10 +15,9 @@ namespace Clippit.Tests.Common { public class MetricsGetterTests : TestsBase { - public MetricsGetterTests(ITestOutputHelper log) : base(log) - { - } - + public MetricsGetterTests(ITestOutputHelper log) + : base(log) { } + [Theory] [InlineData("Presentation.pptx")] [InlineData("Spreadsheet.xlsx")] @@ -61,7 +60,6 @@ public void MG001(string name) Assert.NotNull(metrics); } - } } diff --git a/Clippit.Tests/Common/OpenXmlRegexTests.cs b/Clippit.Tests/Common/OpenXmlRegexTests.cs index 1f2b0c88..02ef3973 100644 --- a/Clippit.Tests/Common/OpenXmlRegexTests.cs +++ b/Clippit.Tests/Common/OpenXmlRegexTests.cs @@ -16,10 +16,9 @@ namespace Clippit.Tests.Common { public class OpenXmlRegexTests : TestsBase { - public OpenXmlRegexTests(ITestOutputHelper log) : base(log) - { - } - + public OpenXmlRegexTests(ITestOutputHelper log) + : base(log) { } + private const WordprocessingDocumentType DocumentType = WordprocessingDocumentType.Document; private const string LeftDoubleQuotationMarks = @"[\u0022“„«»”]"; @@ -27,7 +26,7 @@ public OpenXmlRegexTests(ITestOutputHelper log) : base(log) private const string RightDoubleQuotationMarks = @"[\u0022”‟»«“]"; private const string QuotationMarksDocumentXmlString = -@" + @" @@ -50,7 +49,7 @@ public OpenXmlRegexTests(ITestOutputHelper log) : base(log) "; private const string QuotationMarksAndTrackedChangesDocumentXmlString = -@" + @" @@ -102,7 +101,7 @@ public OpenXmlRegexTests(ITestOutputHelper log) : base(log) "; private const string SymbolsAndTrackedChangesDocumentXmlString = -@" + @" @@ -133,7 +132,7 @@ public OpenXmlRegexTests(ITestOutputHelper log) : base(log) "; private const string FieldsDocumentXmlString = -@" + @" @@ -216,9 +215,7 @@ private static string InnerText(XContainer e) private static string InnerDelText(XContainer e) { - return e.Descendants(W.delText) - .Select(delText => delText.Value) - .StringConcatenate(); + return e.Descendants(W.delText).Select(delText => delText.Value).StringConcatenate(); } [Fact] @@ -230,7 +227,8 @@ public void CanReplaceTextWithQuotationMarks() Assert.Equal( "Text can be enclosed in “normal double quotes” and in «double angle quotation marks».", - innerText); + innerText + ); using var stream = new MemoryStream(); using var wordDocument = WordprocessingDocument.Create(stream, DocumentType); @@ -247,7 +245,8 @@ public void CanReplaceTextWithQuotationMarks() Assert.Equal(2, count); Assert.Equal( "Text can be enclosed in ‘changed normal double quotes’ and in ‘changed double angle quotation marks’.", - innerText); + innerText + ); } [Fact] @@ -259,7 +258,8 @@ public void CanReplaceTextWithQuotationMarksAndAddTrackedChangesWhenReplacing() Assert.Equal( "Text can be enclosed in “normal double quotes” and in «double angle quotation marks».", - innerText); + innerText + ); using var stream = new MemoryStream(); using var wordDocument = WordprocessingDocument.Create(stream, DocumentType); @@ -276,7 +276,8 @@ public void CanReplaceTextWithQuotationMarksAndAddTrackedChangesWhenReplacing() Assert.Equal(2, count); Assert.Equal( "Text can be enclosed in ‘changed normal double quotes’ and in ‘changed double angle quotation marks’.", - innerText); + innerText + ); Assert.Contains(p.Elements(W.ins), e => InnerText(e) == "‘changed normal double quotes’"); Assert.Contains(p.Elements(W.ins), e => InnerText(e) == "‘changed double angle quotation marks’"); @@ -294,7 +295,8 @@ public void CanReplaceTextWithQuotationMarksAndTrackedChanges() Assert.Equal( "Text can be enclosed in “normal double quotes” and in «double angle quotation marks».", - innerText); + innerText + ); using var stream = new MemoryStream(); using var wordDocument = WordprocessingDocument.Create(stream, DocumentType); @@ -311,7 +313,8 @@ public void CanReplaceTextWithQuotationMarksAndTrackedChanges() Assert.Equal(2, count); Assert.Equal( "Text can be enclosed in ‘changed normal double quotes’ and in ‘changed double angle quotation marks’.", - innerText); + innerText + ); Assert.Contains(p.Elements(W.ins), e => InnerText(e) == "‘changed normal double quotes’"); Assert.Contains(p.Elements(W.ins), e => InnerText(e) == "‘changed double angle quotation marks’"); @@ -341,9 +344,14 @@ public void CanReplaceTextWithSymbolsAndTrackedChanges() Assert.Equal(1, count); Assert.Equal("We can also use symbols such as \uF028 or \uF028.", innerText); - Assert.Contains(p.Descendants(W.ins), ins => ins.Descendants(W.sym).Any( - sym => sym.Attribute(W.font).Value == "Wingdings" && - sym.Attribute(W._char).Value == "F028")); + Assert.Contains( + p.Descendants(W.ins), + ins => + ins.Descendants(W.sym) + .Any(sym => + sym.Attribute(W.font).Value == "Wingdings" && sym.Attribute(W._char).Value == "F028" + ) + ); } [Fact] @@ -353,8 +361,10 @@ public void CanReplaceTextWithFields() var p = partDocument.Descendants(W.p).Last(); var innerText = InnerText(p); - Assert.Equal("As stated in Article {__1} and this Section {__1.1}, this is described in Schedule C (Performance Framework).", - innerText); + Assert.Equal( + "As stated in Article {__1} and this Section {__1.1}, this is described in Schedule C (Performance Framework).", + innerText + ); using var stream = new MemoryStream(); using var wordDocument = WordprocessingDocument.Create(stream, DocumentType); @@ -369,7 +379,10 @@ public void CanReplaceTextWithFields() innerText = InnerText(p); Assert.Equal(1, count); - Assert.Equal("As stated in Article {__1} and this Section {__1.1}, this is described in Exhibit 4.", innerText); + Assert.Equal( + "As stated in Article {__1} and this Section {__1.1}, this is described in Exhibit 4.", + innerText + ); } } } diff --git a/Clippit.Tests/Common/Samples/ChartUpdaterSamples.cs b/Clippit.Tests/Common/Samples/ChartUpdaterSamples.cs index 5d951750..fda18a62 100644 --- a/Clippit.Tests/Common/Samples/ChartUpdaterSamples.cs +++ b/Clippit.Tests/Common/Samples/ChartUpdaterSamples.cs @@ -10,13 +10,11 @@ namespace Clippit.Tests.Common.Samples { public class ChartUpdaterSamples : TestsBase { - public ChartUpdaterSamples(ITestOutputHelper log) : base(log) - { - } - - private static string GetFilePath(string path) => - Path.Combine("../../../Common/Samples/ChartUpdater/", path); - + public ChartUpdaterSamples(ITestOutputHelper log) + : base(log) { } + + private static string GetFilePath(string path) => Path.Combine("../../../Common/Samples/ChartUpdater/", path); + [Theory] [InlineData("Chart-Cached-Data-01.docx")] [InlineData("Chart-Cached-Data-02.docx")] @@ -39,7 +37,7 @@ public void UpdateWords(string fileName) var srcFile = new FileInfo(GetFilePath(fileName)); var fName = Path.Combine(TempDir, srcFile.Name); File.Copy(srcFile.FullName, fName, true); - + var fi = new FileInfo(fName); var newFileName = "Updated-" + fi.Name; var fi2 = new FileInfo(Path.Combine(TempDir, newFileName)); @@ -48,103 +46,53 @@ public void UpdateWords(string fileName) using var wDoc = WordprocessingDocument.Open(fi2.FullName, true); var chart1Data = new ChartData { - SeriesNames = new[] { - "Car", - "Truck", - "Van", - "Bike", - "Boat", - }, + SeriesNames = new[] { "Car", "Truck", "Van", "Bike", "Boat" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Q1", - "Q2", - "Q3", - "Q4", - }, + CategoryNames = new[] { "Q1", "Q2", "Q3", "Q4" }, Values = new[] { - new double[] { - 100, 310, 220, 450, - }, - new double[] { - 200, 300, 350, 411, - }, - new double[] { - 80, 120, 140, 600, - }, - new double[] { - 120, 100, 140, 400, - }, - new double[] { - 200, 210, 210, 480, - }, + new double[] { 100, 310, 220, 450 }, + new double[] { 200, 300, 350, 411 }, + new double[] { 80, 120, 140, 600 }, + new double[] { 120, 100, 140, 400 }, + new double[] { 200, 210, 210, 480 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart1", chart1Data); var chart2Data = new ChartData { - SeriesNames = new[] { - "Series" - }, + SeriesNames = new[] { "Series" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Cars", - "Trucks", - "Vans", - "Boats", - }, - Values = new[] - { - new double[] { - 320, 112, 64, 80, - }, - }, + CategoryNames = new[] { "Cars", "Trucks", "Vans", "Boats" }, + Values = new[] { new double[] { 320, 112, 64, 80 } }, }; ChartUpdater.UpdateChart(wDoc, "Chart2", chart2Data); var chart3Data = new ChartData { - SeriesNames = new[] { - "X1", - "X2", - "X3", - "X4", - "X5", - "X6", - }, + SeriesNames = new[] { "X1", "X2", "X3", "X4", "X5", "X6" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { - "Y1", - "Y2", - "Y3", - "Y4", - "Y5", - "Y6", - }, + CategoryNames = new[] { "Y1", "Y2", "Y3", "Y4", "Y5", "Y6" }, Values = new[] { - new[] { 3.0, 2.1, .7, .7, 2.1, 3.0, }, - new[] { 3.0, 2.1, .8, .8, 2.1, 3.0, }, - new[] { 3.0, 2.4, 1.2, 1.2, 2.4, 3.0, }, - new[] { 3.0, 2.7, 1.7, 1.7, 2.7, 3.0, }, - new[] { 3.0, 2.9, 2.5, 2.5, 2.9, 3.0, }, - new[] { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, }, + new[] { 3.0, 2.1, .7, .7, 2.1, 3.0 }, + new[] { 3.0, 2.1, .8, .8, 2.1, 3.0 }, + new[] { 3.0, 2.4, 1.2, 1.2, 2.4, 3.0 }, + new[] { 3.0, 2.7, 1.7, 1.7, 2.7, 3.0 }, + new[] { 3.0, 2.9, 2.5, 2.5, 2.9, 3.0 }, + new[] { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart3", chart3Data); var chart4Data = new ChartData { - SeriesNames = new[] { - "Car", - "Truck", - "Van", - }, + SeriesNames = new[] { "Car", "Truck", "Van" }, CategoryDataType = ChartDataType.DateTime, CategoryFormatCode = 14, - CategoryNames = new[] { + CategoryNames = new[] + { ToExcelInteger(new DateTime(2013, 9, 1)), ToExcelInteger(new DateTime(2013, 9, 2)), ToExcelInteger(new DateTime(2013, 9, 3)), @@ -168,19 +116,12 @@ public void UpdateWords(string fileName) }, Values = new[] { - new double[] { - 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 8, 8, 9, - }, - new double[] { - 2, 3, 3, 4, 4, 5, 6, 7, 8, 7, 8, 9, 9, 9, 7, 8, 9, 9, 10, 11, - }, - new double[] { - 2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 3, 4, 5, 5, 4, - }, + new double[] { 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 5, 4, 5, 6, 7, 8, 7, 8, 8, 9 }, + new double[] { 2, 3, 3, 4, 4, 5, 6, 7, 8, 7, 8, 9, 9, 9, 7, 8, 9, 9, 10, 11 }, + new double[] { 2, 3, 3, 3, 3, 2, 2, 2, 3, 2, 3, 3, 4, 4, 4, 3, 4, 5, 5, 4 }, }, }; ChartUpdater.UpdateChart(wDoc, "Chart4", chart4Data); - } [Theory] @@ -191,7 +132,7 @@ public void UpdatePowerPoints(string fileName) var srcFile = new FileInfo(GetFilePath(fileName)); var fName = Path.Combine(TempDir, srcFile.Name); File.Copy(srcFile.FullName, fName, true); - + var fi = new FileInfo(fName); var newFileName = "Updated-" + srcFile.Name; var fi2 = new FileInfo(Path.Combine(TempDir, newFileName)); @@ -200,13 +141,14 @@ public void UpdatePowerPoints(string fileName) using var pDoc = PresentationDocument.Open(fi2.FullName, true); var chart1Data = new ChartData { - SeriesNames = new[] { "Car", "Truck", "Van", }, + SeriesNames = new[] { "Car", "Truck", "Van" }, CategoryDataType = ChartDataType.String, - CategoryNames = new[] { "Q1", "Q2", "Q3", "Q4", }, + CategoryNames = new[] { "Q1", "Q2", "Q3", "Q4" }, Values = new[] { - new double[] { 320, 310, 320, 330, }, new double[] { 201, 224, 230, 221, }, - new double[] { 180, 200, 220, 230, }, + new double[] { 320, 310, 320, 330 }, + new double[] { 201, 224, 230, 221 }, + new double[] { 180, 200, 220, 230 }, }, }; ChartUpdater.UpdateChart(pDoc, 1, chart1Data); diff --git a/Clippit.Tests/Common/Samples/MetricsGetterSamples.cs b/Clippit.Tests/Common/Samples/MetricsGetterSamples.cs index eadd5906..b18e8bf6 100644 --- a/Clippit.Tests/Common/Samples/MetricsGetterSamples.cs +++ b/Clippit.Tests/Common/Samples/MetricsGetterSamples.cs @@ -6,16 +6,13 @@ namespace Clippit.Tests.Common.Samples { public class MetricsGetterSamples : TestsBase { - public MetricsGetterSamples(ITestOutputHelper log) : base(log) - { - } - - private static string GetFilePath(string path) => - Path.Combine("../../../Common/Samples/MetricsGetter/", path); + public MetricsGetterSamples(ITestOutputHelper log) + : base(log) { } + private static string GetFilePath(string path) => Path.Combine("../../../Common/Samples/MetricsGetter/", path); [Theory] - [InlineData("ContentControls.docx", false)] // No text from content controls + [InlineData("ContentControls.docx", false)] // No text from content controls [InlineData("ContentControls.docx", true)] // With text from content controls [InlineData("TrackedRevisions.docx", true)] // Tracked Revisions [InlineData("Styles.docx", true)] // Style Hierarchy @@ -26,16 +23,16 @@ public void Word(string fileName, bool includeTextInControls) var metrics = MetricsGetter.GetMetrics(fi.FullName, settings); Log.WriteLine(metrics.ToString()); } - + [Fact] public void Excel() { var fi = new FileInfo(GetFilePath("Tables.xlsx")); var settings = new MetricsGetterSettings - { - IncludeTextInContentControls = false, - IncludeXlsxTableCellData = true - }; + { + IncludeTextInContentControls = false, + IncludeXlsxTableCellData = true, + }; var metrics = MetricsGetter.GetMetrics(fi.FullName, settings); Log.WriteLine(metrics.ToString()); } diff --git a/Clippit.Tests/Common/Samples/OpenXmlRegexSamples.cs b/Clippit.Tests/Common/Samples/OpenXmlRegexSamples.cs index 857d28c3..ad0fefc6 100644 --- a/Clippit.Tests/Common/Samples/OpenXmlRegexSamples.cs +++ b/Clippit.Tests/Common/Samples/OpenXmlRegexSamples.cs @@ -11,12 +11,10 @@ namespace Clippit.Tests.Common.Samples { public class OpenXmlRegexSamples : TestsBase { - public OpenXmlRegexSamples(ITestOutputHelper log) : base(log) - { - } - - private static string GetFilePath(string path) => - Path.Combine("../../../Common/Samples/OpenXmlRegex/", path); + public OpenXmlRegexSamples(ITestOutputHelper log) + : base(log) { } + + private static string GetFilePath(string path) => Path.Combine("../../../Common/Samples/OpenXmlRegex/", path); [Fact] public void WordSample1() @@ -43,8 +41,11 @@ public void WordSample1() // Match content, with callback (paragraph 1) content = xDoc.Descendants(W.p).Take(1); regex = new Regex("video", RegexOptions.IgnoreCase); - OpenXmlRegex.Match(content, regex, (element, match) => - Log.WriteLine("Example #3 Found value: >{0}<", match.Value)); + OpenXmlRegex.Match( + content, + regex, + (element, match) => Log.WriteLine("Example #3 Found value: >{0}<", match.Value) + ); // Replace content, beginning of paragraph (paragraph 2) content = xDoc.Descendants(W.p).Skip(1).Take(1); @@ -205,7 +206,12 @@ public void WordSample1() // Replace or comment on symbols (paragraph 23) paras = xDoc.Descendants(W.p).Skip(22).Take(1).ToList(); - count = OpenXmlRegex.Replace(paras, new Regex($"{oldPhone}"), $"{newPhone} (replaced with new phone)", null); + count = OpenXmlRegex.Replace( + paras, + new Regex($"{oldPhone}"), + $"{newPhone} (replaced with new phone)", + null + ); count += OpenXmlRegex.Replace(paras, new Regex($"({pencil})"), "$1 (same pencil)", null); count += OpenXmlRegex.Replace(paras, new Regex($"({spider})"), "$1 (same spider)", null); Log.WriteLine("Example #25 Replaced: {0}", count); @@ -217,7 +223,7 @@ public void WordSample1() public void WordSample2() { var sourceDoc = new FileInfo(GetFilePath("TestDocument.docx")); - var newDoc = new FileInfo(Path.Combine(TempDir,"Modified.docx")); + var newDoc = new FileInfo(Path.Combine(TempDir, "Modified.docx")); File.Copy(sourceDoc.FullName, newDoc.FullName); using var wDoc = WordprocessingDocument.Open(newDoc.FullName, true); @@ -236,23 +242,22 @@ public void WordSample2() wDoc.MainDocumentPart.PutXDocument(); } - + private static object TransformEnvironmentNewLineToParagraph(XNode node) { if (node is XElement element) { - if (element.Name == W.p) - { - - } + if (element.Name == W.p) { } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(TransformEnvironmentNewLineToParagraph)); + element.Nodes().Select(TransformEnvironmentNewLineToParagraph) + ); } return node; } - + [Fact] public void PowerPointSample() { diff --git a/Clippit.Tests/Common/Samples/TextReplacerSamples.cs b/Clippit.Tests/Common/Samples/TextReplacerSamples.cs index c694972a..377b22bb 100644 --- a/Clippit.Tests/Common/Samples/TextReplacerSamples.cs +++ b/Clippit.Tests/Common/Samples/TextReplacerSamples.cs @@ -9,12 +9,10 @@ namespace Clippit.Tests.Common.Samples { public class TextReplacerSamples : TestsBase { - public TextReplacerSamples(ITestOutputHelper log) : base(log) - { - } - - private static string GetFilePath(string path) => - Path.Combine("../../../Common/Samples/TextReplacer/", path); + public TextReplacerSamples(ITestOutputHelper log) + : base(log) { } + + private static string GetFilePath(string path) => Path.Combine("../../../Common/Samples/TextReplacer/", path); [Theory] [InlineData("PowerPoint/Test01.pptx")] @@ -37,21 +35,21 @@ public void Word() using (var doc = WordprocessingDocument.Open(Path.Combine(TempDir, "Test01.docx"), true)) TextReplacer.SearchAndReplace(doc, "the", "this", false); - + try { using var doc = WordprocessingDocument.Open(Path.Combine(TempDir, "Test02.docx"), true); TextReplacer.SearchAndReplace(doc, "the", "this", false); } catch (Exception) { } - + try { using var doc = WordprocessingDocument.Open(Path.Combine(TempDir, "Test03.docx"), true); TextReplacer.SearchAndReplace(doc, "the", "this", false); } catch (Exception) { } - + using (var doc = WordprocessingDocument.Open(Path.Combine(TempDir, "Test04.docx"), true)) TextReplacer.SearchAndReplace(doc, "the", "this", true); using (var doc = WordprocessingDocument.Open(Path.Combine(TempDir, "Test05.docx"), true)) diff --git a/Clippit.Tests/Common/UnicodeMapperTests.cs b/Clippit.Tests/Common/UnicodeMapperTests.cs index 71683d67..0d6dbb26 100644 --- a/Clippit.Tests/Common/UnicodeMapperTests.cs +++ b/Clippit.Tests/Common/UnicodeMapperTests.cs @@ -40,18 +40,18 @@ public void CanStringifyRunAndTextElements() [Fact] public void CanStringifySpecialElements() { - Assert.Equal(UnicodeMapper.CarriageReturn, - UnicodeMapper.RunToString(new XElement(W.cr)).First()); - Assert.Equal(UnicodeMapper.CarriageReturn, - UnicodeMapper.RunToString(new XElement(W.br)).First()); - Assert.Equal(UnicodeMapper.FormFeed, - UnicodeMapper.RunToString(new XElement(W.br, new XAttribute(W.type, "page"))).First()); - Assert.Equal(UnicodeMapper.NonBreakingHyphen, - UnicodeMapper.RunToString(new XElement(W.noBreakHyphen)).First()); - Assert.Equal(UnicodeMapper.SoftHyphen, - UnicodeMapper.RunToString(new XElement(W.softHyphen)).First()); - Assert.Equal(UnicodeMapper.HorizontalTabulation, - UnicodeMapper.RunToString(new XElement(W.tab)).First()); + Assert.Equal(UnicodeMapper.CarriageReturn, UnicodeMapper.RunToString(new XElement(W.cr)).First()); + Assert.Equal(UnicodeMapper.CarriageReturn, UnicodeMapper.RunToString(new XElement(W.br)).First()); + Assert.Equal( + UnicodeMapper.FormFeed, + UnicodeMapper.RunToString(new XElement(W.br, new XAttribute(W.type, "page"))).First() + ); + Assert.Equal( + UnicodeMapper.NonBreakingHyphen, + UnicodeMapper.RunToString(new XElement(W.noBreakHyphen)).First() + ); + Assert.Equal(UnicodeMapper.SoftHyphen, UnicodeMapper.RunToString(new XElement(W.softHyphen)).First()); + Assert.Equal(UnicodeMapper.HorizontalTabulation, UnicodeMapper.RunToString(new XElement(W.tab)).First()); } [Fact] @@ -89,27 +89,27 @@ public void CanCreateCoalescedRuns() [Fact] public void CanMapSymbols() { - var sym1 = new XElement(W.sym, - new XAttribute(W.font, "Wingdings"), - new XAttribute(W._char, "F028")); + var sym1 = new XElement(W.sym, new XAttribute(W.font, "Wingdings"), new XAttribute(W._char, "F028")); var charFromSym1 = UnicodeMapper.SymToChar(sym1); var symFromChar1 = UnicodeMapper.CharToRunChild(charFromSym1); - var sym2 = new XElement(W.sym, - new XAttribute(W._char, "F028"), - new XAttribute(W.font, "Wingdings")); + var sym2 = new XElement(W.sym, new XAttribute(W._char, "F028"), new XAttribute(W.font, "Wingdings")); var charFromSym2 = UnicodeMapper.SymToChar(sym2); - var sym3 = new XElement(W.sym, + var sym3 = new XElement( + W.sym, new XAttribute(XNamespace.Xmlns + "w", W.w), new XAttribute(W.font, "Wingdings"), - new XAttribute(W._char, "F028")); + new XAttribute(W._char, "F028") + ); var charFromSym3 = UnicodeMapper.SymToChar(sym3); - var sym4 = new XElement(W.sym, + var sym4 = new XElement( + W.sym, new XAttribute(XNamespace.Xmlns + "w", W.w), new XAttribute(W.font, "Webdings"), - new XAttribute(W._char, "F028")); + new XAttribute(W._char, "F028") + ); var charFromSym4 = UnicodeMapper.SymToChar(sym4); var symFromChar4 = UnicodeMapper.CharToRunChild(charFromSym4); diff --git a/Clippit.Tests/Excel/Samples/SmlDataRetrieverSamples.cs b/Clippit.Tests/Excel/Samples/SmlDataRetrieverSamples.cs index 7ab9e11c..1dcccedd 100644 --- a/Clippit.Tests/Excel/Samples/SmlDataRetrieverSamples.cs +++ b/Clippit.Tests/Excel/Samples/SmlDataRetrieverSamples.cs @@ -7,10 +7,9 @@ namespace Clippit.Tests.Excel.Samples { public class SmlDataRetrieverSamples : TestsBase { - public SmlDataRetrieverSamples(ITestOutputHelper log) : base(log) - { - } - + public SmlDataRetrieverSamples(ITestOutputHelper log) + : base(log) { } + private static string GetFilePath(string path) => Path.Combine("../../../Excel/Samples/SmlDataRetriever/", path); diff --git a/Clippit.Tests/Excel/Samples/SpreadsheetWriterSamples.cs b/Clippit.Tests/Excel/Samples/SpreadsheetWriterSamples.cs index 43adba06..3145ee56 100644 --- a/Clippit.Tests/Excel/Samples/SpreadsheetWriterSamples.cs +++ b/Clippit.Tests/Excel/Samples/SpreadsheetWriterSamples.cs @@ -8,10 +8,9 @@ namespace Clippit.Tests.Excel.Samples { public class SpreadsheetWriterSamples : TestsBase { - public SpreadsheetWriterSamples(ITestOutputHelper log) : base(log) - { - } - + public SpreadsheetWriterSamples(ITestOutputHelper log) + : base(log) { } + [Fact] public void Sample1() { @@ -25,11 +24,7 @@ public void Sample1() TableName = "NamesAndRates", ColumnHeadings = new[] { - new CellDfn - { - Value = "Name", - Bold = true, - }, + new CellDfn { Value = "Name", Bold = true }, new CellDfn { Value = "Age", @@ -41,7 +36,7 @@ public void Sample1() Value = "Rate", Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Left, - } + }, }, Rows = new[] { @@ -49,50 +44,40 @@ public void Sample1() { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "Eric", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = 50, - }, - new CellDfn { + new CellDfn { CellDataType = CellDataType.String, Value = "Eric" }, + new CellDfn { CellDataType = CellDataType.Number, Value = 50 }, + new CellDfn + { CellDataType = CellDataType.Number, Value = (decimal)45.00, FormatCode = "0.00", }, - } + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "Bob", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = 42, - }, - new CellDfn { + new CellDfn { CellDataType = CellDataType.String, Value = "Bob" }, + new CellDfn { CellDataType = CellDataType.Number, Value = 42 }, + new CellDfn + { CellDataType = CellDataType.Number, Value = (decimal)78.00, FormatCode = "0.00", }, - } + }, }, - } - } - } + }, + }, + }, }; - + var fileName = Path.Combine(TempDir, "Sw_Example1.xlsx"); using var stream = File.Open(fileName, FileMode.OpenOrCreate); wb.WriteTo(stream); } - + [Fact] public void Sample2() { @@ -105,11 +90,7 @@ public void Sample2() Name = "MyFirstSheet", ColumnHeadings = new[] { - new CellDfn - { - Value = "DataType", - Bold = true, - }, + new CellDfn { Value = "DataType", Bold = true }, new CellDfn { Value = "Value", @@ -123,180 +104,120 @@ public void Sample2() { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "Boolean", - }, - new CellDfn { - CellDataType = CellDataType.Boolean, - Value = true, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "Boolean" }, + new CellDfn { CellDataType = CellDataType.Boolean, Value = true }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "Boolean", - }, - new CellDfn { - CellDataType = CellDataType.Boolean, - Value = false, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "Boolean" }, + new CellDfn { CellDataType = CellDataType.Boolean, Value = false }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "String", - }, - new CellDfn { + new CellDfn { CellDataType = CellDataType.String, Value = "String" }, + new CellDfn + { CellDataType = CellDataType.String, Value = "A String", HorizontalCellAlignment = HorizontalCellAlignment.Right, }, - } + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "int", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = 100, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "int" }, + new CellDfn { CellDataType = CellDataType.Number, Value = 100 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "int?", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = (int?)100, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "int?" }, + new CellDfn { CellDataType = CellDataType.Number, Value = (int?)100 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "int? (is null)", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = null, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "int? (is null)" }, + new CellDfn { CellDataType = CellDataType.Number, Value = null }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "uint", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = (uint)101, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "uint" }, + new CellDfn { CellDataType = CellDataType.Number, Value = (uint)101 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "long", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = long.MaxValue, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "long" }, + new CellDfn { CellDataType = CellDataType.Number, Value = long.MaxValue }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "float", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = (float)123.45, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "float" }, + new CellDfn { CellDataType = CellDataType.Number, Value = (float)123.45 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "double", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = 123.45, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "double" }, + new CellDfn { CellDataType = CellDataType.Number, Value = 123.45 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { - CellDataType = CellDataType.String, - Value = "decimal", - }, - new CellDfn { - CellDataType = CellDataType.Number, - Value = (decimal)123.45, - }, - } + new CellDfn { CellDataType = CellDataType.String, Value = "decimal" }, + new CellDfn { CellDataType = CellDataType.Number, Value = (decimal)123.45 }, + }, }, new RowDfn { Cells = new[] { - new CellDfn { + new CellDfn + { CellDataType = CellDataType.Date, Value = new DateTime(2012, 1, 8), FormatCode = "mm-dd-yy", }, - new CellDfn { + new CellDfn + { CellDataType = CellDataType.Date, Value = new DateTime(2012, 1, 9), FormatCode = "mm-dd-yy", Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Center, }, - } + }, }, - } - } - } + }, + }, + }, }; - + var fileName = Path.Combine(TempDir, "Sw_Example2.xlsx"); using var stream = File.Open(fileName, FileMode.OpenOrCreate); wb.WriteTo(stream); diff --git a/Clippit.Tests/Excel/Samples/WorksheetAccessorSamples.cs b/Clippit.Tests/Excel/Samples/WorksheetAccessorSamples.cs index c21567af..9ef304a1 100644 --- a/Clippit.Tests/Excel/Samples/WorksheetAccessorSamples.cs +++ b/Clippit.Tests/Excel/Samples/WorksheetAccessorSamples.cs @@ -7,10 +7,9 @@ namespace Clippit.Tests.Excel.Samples { public class WorksheetAccessorSamples : TestsBase { - public WorksheetAccessorSamples(ITestOutputHelper log) : base(log) - { - } - + public WorksheetAccessorSamples(ITestOutputHelper log) + : base(log) { } + private static string GetFilePath(string path) => Path.Combine("../../../Excel/Samples/WorksheetAccessor/", path); @@ -19,7 +18,7 @@ public void Formulas1() { var sourceFile = GetFilePath("Formulas1/Formulas.xlsx"); // Change sheet name in formulas - using (var streamDoc = new OpenXmlMemoryStreamDocument( OpenXmlPowerToolsDocument.FromFileName(sourceFile))) + using (var streamDoc = new OpenXmlMemoryStreamDocument(OpenXmlPowerToolsDocument.FromFileName(sourceFile))) { using (var doc = streamDoc.GetSpreadsheetDocument()) { @@ -48,8 +47,7 @@ public void PivotTables1() var qsu = new FileInfo(Path.Combine(TempDir, "QuarterlyPivot.xlsx")); var row = 1; - using (var streamDoc = new OpenXmlMemoryStreamDocument( - OpenXmlPowerToolsDocument.FromFileName(qs.FullName))) + using (var streamDoc = new OpenXmlMemoryStreamDocument(OpenXmlPowerToolsDocument.FromFileName(qs.FullName))) { using (var doc = streamDoc.GetSpreadsheetDocument()) { @@ -431,39 +429,61 @@ public void PivotTables1() }); #endif - var southIndex = WorksheetAccessor.GetStyleIndex(doc, 0, 8, 1, 2, + var southIndex = WorksheetAccessor.GetStyleIndex( + doc, + 0, + 8, + 1, + 2, new WorksheetAccessor.CellAlignment { - HorizontalAlignment = WorksheetAccessor.CellAlignment.Horizontal.Center + HorizontalAlignment = WorksheetAccessor.CellAlignment.Horizontal.Center, }, - true, false); + true, + false + ); var gradient = new WorksheetAccessor.GradientFill(90); gradient.AddStop( - new WorksheetAccessor.GradientStop(0, new WorksheetAccessor.ColorInfo("FF92D050"))); + new WorksheetAccessor.GradientStop(0, new WorksheetAccessor.ColorInfo("FF92D050")) + ); gradient.AddStop( - new WorksheetAccessor.GradientStop(1, new WorksheetAccessor.ColorInfo("FF0070C0"))); - var northIndex = WorksheetAccessor.GetStyleIndex(doc, 0, - WorksheetAccessor.GetFontIndex(doc, + new WorksheetAccessor.GradientStop(1, new WorksheetAccessor.ColorInfo("FF0070C0")) + ); + var northIndex = WorksheetAccessor.GetStyleIndex( + doc, + 0, + WorksheetAccessor.GetFontIndex( + doc, new WorksheetAccessor.Font { Italic = true, Size = 8, - Color = new WorksheetAccessor.ColorInfo(WorksheetAccessor.ColorInfo.ColorType.Theme, - 1), + Color = new WorksheetAccessor.ColorInfo(WorksheetAccessor.ColorInfo.ColorType.Theme, 1), Name = "Times New Roman", - Family = 1 - }), + Family = 1, + } + ), WorksheetAccessor.GetFillIndex(doc, gradient), - WorksheetAccessor.GetBorderIndex(doc, new WorksheetAccessor.Border - { - DiagonalDown = true, - Diagonal = - new WorksheetAccessor.BorderLine(WorksheetAccessor.BorderLine.LineStyle.Thin, - new WorksheetAccessor.ColorInfo("FF616100")) - }), - null, false, false); - WorksheetAccessor.CheckNumberFormat(doc, 100, - "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"); + WorksheetAccessor.GetBorderIndex( + doc, + new WorksheetAccessor.Border + { + DiagonalDown = true, + Diagonal = new WorksheetAccessor.BorderLine( + WorksheetAccessor.BorderLine.LineStyle.Thin, + new WorksheetAccessor.ColorInfo("FF616100") + ), + } + ), + null, + false, + false + ); + WorksheetAccessor.CheckNumberFormat( + doc, + 100, + "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)" + ); var amountIndex = WorksheetAccessor.GetStyleIndex(doc, 100, 0, 0, 0, null, false, false); using (var source = new StreamReader(GetFilePath("PivotTables1/PivotData.txt"))) @@ -485,8 +505,12 @@ public void PivotTables1() ms.SetCellValue(row, column++, num); } else if (item == "Accessories") - ms.SetCellValue(row, column++, item, - WorksheetAccessor.GetStyleIndex(doc, "Good")); + ms.SetCellValue( + row, + column++, + item, + WorksheetAccessor.GetStyleIndex(doc, "Good") + ); else if (item == "South") ms.SetCellValue(row, column++, item, southIndex); else if (item == "North") @@ -519,11 +543,13 @@ public void PivotTables1() streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(TempDir, "NewPivot.xlsx")); } - // Add pivot table to existing spreadsheet // Demonstrate multiple data fields - using (var streamDoc = new OpenXmlMemoryStreamDocument( - OpenXmlPowerToolsDocument.FromFileName(GetFilePath("PivotTables1/QuarterlyUnitSales.xlsx")))) + using ( + var streamDoc = new OpenXmlMemoryStreamDocument( + OpenXmlPowerToolsDocument.FromFileName(GetFilePath("PivotTables1/QuarterlyUnitSales.xlsx")) + ) + ) { using (var doc = streamDoc.GetSpreadsheetDocument()) { @@ -544,6 +570,5 @@ public void PivotTables1() streamDoc.GetModifiedSmlDocument().SaveAs(Path.Combine(TempDir, "QuarterlyUnitSalesWithPivot.xlsx")); } } - } } diff --git a/Clippit.Tests/Excel/SmlCellFormatterTests.cs b/Clippit.Tests/Excel/SmlCellFormatterTests.cs index d7f3f910..d21ad3c4 100644 --- a/Clippit.Tests/Excel/SmlCellFormatterTests.cs +++ b/Clippit.Tests/Excel/SmlCellFormatterTests.cs @@ -14,10 +14,9 @@ namespace Clippit.Tests.Excel { public class SmlCellFormatterTests : TestsBase { - public SmlCellFormatterTests(ITestOutputHelper log) : base(log) - { - } - + public SmlCellFormatterTests(ITestOutputHelper log) + : base(log) { } + [Theory] [InlineData("General", "0", "0", null)] [InlineData("0", "1.1000000000000001", "1", null)] @@ -80,7 +79,6 @@ public SmlCellFormatterTests(ITestOutputHelper log) : base(log) [InlineData("mm:ss.0", "42344.295445092591", "05:26:456", null)] [InlineData("##0.0E+0", "100.0", "100.0E+0", null)] [InlineData("##0.0E+0", "543.210", "543.2E+0", null)] - public void CF001(string formatCode, string value, string expected, string expectedColor) { var r = SmlCellFormatter.FormatCell(formatCode, value, out var color); @@ -116,24 +114,26 @@ public void CF001(string formatCode, string value, string expected, string expec [InlineData("SH152-Custom-Cell-Format.xlsx", "Sheet1", "A1:A1", "1,234,567.0000", null)] [InlineData("SH152-Custom-Cell-Format.xlsx", "Sheet1", "B1:B1", "This is the value: abc", null)] - [InlineData("SH201-Cell-C1-Without-R-Attr.xlsx", "Sheet1", "C1:C1", "3", null)] [InlineData("SH202-Cell-C1-D1-Without-R-Attr.xlsx", "Sheet1", "C1:C1", "3", null)] [InlineData("SH203-Cell-C1-D1-E1-Without-R-Attr.xlsx", "Sheet1", "C1:C1", "3", null)] [InlineData("SH204-Cell-A1-B1-C1-Without-R-Attr.xlsx", "Sheet1", "A1:A1", "1", null)] - public void CF002(string name, string sheetName, string range, string expected, string expectedColor) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceXlsx = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceCopiedToDestXlsx = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx"))); + var sourceCopiedToDestXlsx = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx")) + ); if (!sourceCopiedToDestXlsx.Exists) File.Copy(sourceXlsx.FullName, sourceCopiedToDestXlsx.FullName); var dataTemplateFileNameSuffix = $"-2-Generated-XmlData-{range.Replace(":", "")}.xml"; - var dataXmlFi = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix))); - + var dataXmlFi = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix)) + ); + using var sDoc = SpreadsheetDocument.Open(sourceXlsx.FullName, false); var rangeXml = SmlDataRetriever.RetrieveRange(sDoc, sheetName, range); var displayValue = (string)rangeXml.Descendants("DisplayValue").FirstOrDefault(); diff --git a/Clippit.Tests/Excel/SmlToHtmlConverterTests.cs b/Clippit.Tests/Excel/SmlToHtmlConverterTests.cs index 075b2667..9a355b40 100644 --- a/Clippit.Tests/Excel/SmlToHtmlConverterTests.cs +++ b/Clippit.Tests/Excel/SmlToHtmlConverterTests.cs @@ -13,10 +13,9 @@ namespace Clippit.Tests.Excel { public class SmlToHtmlConverterTests : TestsBase { - public SmlToHtmlConverterTests(ITestOutputHelper log) : base(log) - { - } - + public SmlToHtmlConverterTests(ITestOutputHelper log) + : base(log) { } + // PowerShell oneliner that generates InlineData for all files in a directory // dir | % { '[InlineData("' + $_.Name + '")]' } | clip @@ -51,18 +50,21 @@ public SmlToHtmlConverterTests(ITestOutputHelper log) : base(log) [InlineData("SH129-FmtNumId-20.xlsx", "Sheet1")] [InlineData("SH130-FmtNumId-21.xlsx", "Sheet1")] [InlineData("SH131-FmtNumId-22.xlsx", "Sheet1")] - public void SH005_ConvertSheet(string name, string sheetName) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceXlsx = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceCopiedToDestXlsx = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx"))); + var sourceCopiedToDestXlsx = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx")) + ); if (!sourceCopiedToDestXlsx.Exists) File.Copy(sourceXlsx.FullName, sourceCopiedToDestXlsx.FullName); var dataTemplateFileNameSuffix = "-2-Generated-XmlData-Entire-Sheet.xml"; - var dataXmlFi = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix))); + var dataXmlFi = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix)) + ); using var sDoc = SpreadsheetDocument.Open(sourceXlsx.FullName, false); var settings = new SmlToHtmlConverterSettings(); var rangeXml = SmlDataRetriever.RetrieveSheet(sDoc, sheetName); @@ -108,24 +110,26 @@ public void SH005_ConvertSheet(string name, string sheetName) [InlineData("SH129-FmtNumId-20.xlsx", "Sheet1", "A1:A10")] [InlineData("SH130-FmtNumId-21.xlsx", "Sheet1", "A1:A10")] [InlineData("SH131-FmtNumId-22.xlsx", "Sheet1", "A1:A10")] - public void SH004_ConvertRange(string name, string sheetName, string range) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceXlsx = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceCopiedToDestXlsx = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx"))); + var sourceCopiedToDestXlsx = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx")) + ); if (!sourceCopiedToDestXlsx.Exists) File.Copy(sourceXlsx.FullName, sourceCopiedToDestXlsx.FullName); var dataTemplateFileNameSuffix = $"-2-Generated-XmlData-{range.Replace(":", "")}.xml"; - var dataXmlFi = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix))); + var dataXmlFi = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", dataTemplateFileNameSuffix)) + ); using var sDoc = SpreadsheetDocument.Open(sourceXlsx.FullName, false); var settings = new SmlToHtmlConverterSettings(); var rangeXml = SmlDataRetriever.RetrieveRange(sDoc, sheetName, range); rangeXml.Save(dataXmlFi.FullName); } - [Theory] [InlineData("SH001-Table.xlsx", "MyTable")] @@ -137,17 +141,20 @@ public void SH004_ConvertRange(string name, string sheetName, string range) [InlineData("SH007-One-Cell-Table.xlsx", "Table1")] [InlineData("SH008-Table-With-Tall-Row.xlsx", "Table1")] [InlineData("SH009-Table-With-Wide-Column.xlsx", "Table1")] - public void SH003_ConvertTable(string name, string tableName) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceXlsx = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceCopiedToDestXlsx = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx"))); + var sourceCopiedToDestXlsx = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-1-Source.xlsx")) + ); if (!sourceCopiedToDestXlsx.Exists) File.Copy(sourceXlsx.FullName, sourceCopiedToDestXlsx.FullName); - var dataXmlFi = new FileInfo(Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-2-Generated-XmlData.xml"))); + var dataXmlFi = new FileInfo( + Path.Combine(TempDir, sourceXlsx.Name.Replace(".xlsx", "-2-Generated-XmlData.xml")) + ); using var sDoc = SpreadsheetDocument.Open(sourceXlsx.FullName, false); //var settings = new SmlToHtmlConverterSettings(); var rangeXml = SmlDataRetriever.RetrieveTable(sDoc, tableName); @@ -176,7 +183,6 @@ public void SH001_TableNames(string name, int numberOfTables) var table = SmlDataRetriever.TableNames(sDoc); Assert.Equal(numberOfTables, table.Length); } - } } diff --git a/Clippit.Tests/Excel/SpreadsheetWriterTests.cs b/Clippit.Tests/Excel/SpreadsheetWriterTests.cs index 3c0adcf5..6a42c854 100644 --- a/Clippit.Tests/Excel/SpreadsheetWriterTests.cs +++ b/Clippit.Tests/Excel/SpreadsheetWriterTests.cs @@ -15,69 +15,75 @@ namespace Clippit.Tests.Excel { public class SpreadsheetWriterTests : TestsBase { - public SpreadsheetWriterTests(ITestOutputHelper log) : base(log) - { - } - - private static WorkbookDfn GetSimpleWorkbookDfn() => new() - { - Worksheets = new[] { GetSimpleWorksheetDfn("MyFirstSheet","NamesAndRates") } - }; + public SpreadsheetWriterTests(ITestOutputHelper log) + : base(log) { } - private static WorksheetDfn GetSimpleWorksheetDfn(string name, string table) => new() - { - Name = name, - TableName = table, - ColumnHeadings = - new CellDfn[] + private static WorkbookDfn GetSimpleWorkbookDfn() => + new() { Worksheets = new[] { GetSimpleWorksheetDfn("MyFirstSheet", "NamesAndRates") } }; + + private static WorksheetDfn GetSimpleWorksheetDfn(string name, string table) => + new() + { + Name = name, + TableName = table, + ColumnHeadings = new CellDfn[] { - new() { Value = "Name", Bold = true, }, - new() { Value = "Age", Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Left, }, - new() { Value = "Rate", Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Left, } + new() { Value = "Name", Bold = true }, + new() + { + Value = "Age", + Bold = true, + HorizontalCellAlignment = HorizontalCellAlignment.Left, + }, + new() + { + Value = "Rate", + Bold = true, + HorizontalCellAlignment = HorizontalCellAlignment.Left, + }, }, - Rows = new RowDfn[] - { - new() + Rows = new RowDfn[] { - Cells = new CellDfn[] + new() { - new() { CellDataType = CellDataType.String, Value = "Eric", }, - new() { CellDataType = CellDataType.Number, Value = 50, }, - new() + Cells = new CellDfn[] { - CellDataType = CellDataType.Number, - Value = (decimal)45.00, - FormatCode = "0.00", + new() { CellDataType = CellDataType.String, Value = "Eric" }, + new() { CellDataType = CellDataType.Number, Value = 50 }, + new() + { + CellDataType = CellDataType.Number, + Value = (decimal)45.00, + FormatCode = "0.00", + }, }, - } - }, - new() - { - Cells = new CellDfn[] + }, + new() { - new() { CellDataType = CellDataType.String, Value = "Bob", }, - new() { CellDataType = CellDataType.Number, Value = 42, }, - new() + Cells = new CellDfn[] { - CellDataType = CellDataType.Number, - Value = (decimal)78.00, - FormatCode = "0.00", + new() { CellDataType = CellDataType.String, Value = "Bob" }, + new() { CellDataType = CellDataType.Number, Value = 42 }, + new() + { + CellDataType = CellDataType.Number, + Value = (decimal)78.00, + FormatCode = "0.00", + }, }, - } + }, }, - } - }; - - + }; + [Fact] public void SaveWorkbookToFile() { var wb = GetSimpleWorkbookDfn(); - + var fileName = Path.Combine(TempDir, "SW001-Simple.xlsx"); using (var stream = File.Open(fileName, FileMode.OpenOrCreate)) wb.WriteTo(stream); - + using var sDoc = SpreadsheetDocument.Open(fileName, false); Validate(sDoc, s_spreadsheetExpectedErrors); } @@ -94,7 +100,7 @@ public void SaveWorkbookToStream() using var sDoc = SpreadsheetDocument.Open(stream, false); Validate(sDoc, s_spreadsheetExpectedErrors); } - + [Fact] public void SaveWorkbookWithTwoSheets() { @@ -102,9 +108,9 @@ public void SaveWorkbookWithTwoSheets() { Worksheets = new[] { - GetSimpleWorksheetDfn("MyFirstSheet","NamesAndRates1"), - GetSimpleWorksheetDfn("MySecondSheet","NamesAndRates2") - } + GetSimpleWorksheetDfn("MyFirstSheet", "NamesAndRates1"), + GetSimpleWorksheetDfn("MySecondSheet", "NamesAndRates2"), + }, }; var fileName = Path.Combine(TempDir, "SW001_TwoSheets.xlsx"); @@ -113,7 +119,7 @@ public void SaveWorkbookWithTwoSheets() Validate(fileName); } - + [Fact] public void SaveTablesWithDates() { @@ -122,34 +128,48 @@ WorksheetDfn GetSheet(string name, string tableName) => { Name = name, TableName = tableName, - ColumnHeadings = new [] + ColumnHeadings = new[] { - new CellDfn { CellDataType = CellDataType.String, Bold = true, Value= "Date"} + new CellDfn + { + CellDataType = CellDataType.String, + Bold = true, + Value = "Date", + }, }, - Rows = new [] + Rows = new[] { + new RowDfn { Cells = new CellDfn[] { null } }, new RowDfn { - Cells = new CellDfn[] { null } + Cells = new[] + { + new CellDfn + { + CellDataType = CellDataType.Date, + Value = null, + FormatCode = "mm-dd-yy", + }, + }, }, new RowDfn { - Cells = new[] {new CellDfn {CellDataType = CellDataType.Date, Value = null, FormatCode = "mm-dd-yy"}} + Cells = new[] + { + new CellDfn + { + CellDataType = CellDataType.Date, + Value = DateTime.Now, + FormatCode = "mm-dd-yy", + }, + }, }, - new RowDfn - { - Cells = new[] {new CellDfn {CellDataType = CellDataType.Date, Value = DateTime.Now, FormatCode = "mm-dd-yy"}} - } - } + }, }; var wb = new WorkbookDfn { - Worksheets = new [] - { - GetSheet("Sheet1","Table1"), - GetSheet("Sheet2","Table2") - } + Worksheets = new[] { GetSheet("Sheet1", "Table1"), GetSheet("Sheet2", "Table2") }, }; var fileName = Path.Combine(TempDir, "SW001_TableWithDates.xlsx"); @@ -172,11 +192,7 @@ public void SaveAllDataTypes() Name = "MyFirstSheet", ColumnHeadings = new CellDfn[] { - new() - { - Value = "DataType", - Bold = true, - }, + new() { Value = "DataType", Bold = true }, new() { Value = "Value", @@ -190,178 +206,94 @@ public void SaveAllDataTypes() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "Boolean", - }, - new() - { - CellDataType = CellDataType.Boolean, - Value = true, - }, - } + new() { CellDataType = CellDataType.String, Value = "Boolean" }, + new() { CellDataType = CellDataType.Boolean, Value = true }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "Boolean", - }, - new() - { - CellDataType = CellDataType.Boolean, - Value = false, - }, - } + new() { CellDataType = CellDataType.String, Value = "Boolean" }, + new() { CellDataType = CellDataType.Boolean, Value = false }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "String", - }, + new() { CellDataType = CellDataType.String, Value = "String" }, new() { CellDataType = CellDataType.String, Value = "A String", HorizontalCellAlignment = HorizontalCellAlignment.Right, }, - } + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "int", - }, - new() - { - CellDataType = CellDataType.Number, - Value = 100, - }, - } + new() { CellDataType = CellDataType.String, Value = "int" }, + new() { CellDataType = CellDataType.Number, Value = 100 }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "int?", - }, - new() - { - CellDataType = CellDataType.Number, - Value = (int?)100, - }, - } + new() { CellDataType = CellDataType.String, Value = "int?" }, + new() { CellDataType = CellDataType.Number, Value = (int?)100 }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "int? (is null)", - }, - new() - { - CellDataType = CellDataType.Number, - Value = null, - }, - } + new() { CellDataType = CellDataType.String, Value = "int? (is null)" }, + new() { CellDataType = CellDataType.Number, Value = null }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "uint", - }, - new() - { - CellDataType = CellDataType.Number, - Value = (uint)101, - }, - } + new() { CellDataType = CellDataType.String, Value = "uint" }, + new() { CellDataType = CellDataType.Number, Value = (uint)101 }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "long", - }, - new() - { - CellDataType = CellDataType.Number, - Value = long.MaxValue, - }, - } + new() { CellDataType = CellDataType.String, Value = "long" }, + new() { CellDataType = CellDataType.Number, Value = long.MaxValue }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "float", - }, - new() - { - CellDataType = CellDataType.Number, - Value = (float)123.45, - }, - } + new() { CellDataType = CellDataType.String, Value = "float" }, + new() { CellDataType = CellDataType.Number, Value = (float)123.45 }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "double", - }, - new() - { - CellDataType = CellDataType.Number, - Value = 123.45, - }, - } + new() { CellDataType = CellDataType.String, Value = "double" }, + new() { CellDataType = CellDataType.Number, Value = 123.45 }, + }, }, new() { Cells = new CellDfn[] { - new() - { - CellDataType = CellDataType.String, - Value = "decimal", - }, - new() - { - CellDataType = CellDataType.Number, - Value = (decimal)123.45, - }, - } + new() { CellDataType = CellDataType.String, Value = "decimal" }, + new() { CellDataType = CellDataType.Number, Value = (decimal)123.45 }, + }, }, new() { @@ -381,7 +313,7 @@ public void SaveAllDataTypes() Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Center, }, - } + }, }, new() { @@ -401,26 +333,25 @@ public void SaveAllDataTypes() Bold = true, HorizontalCellAlignment = HorizontalCellAlignment.Center, }, - } + }, }, - } - } - } + }, + }, + }, }; var fileName = Path.Combine(TempDir, "SW002-DataTypes.xlsx"); using (var stream = File.Open(fileName, FileMode.OpenOrCreate)) wb.WriteTo(stream); - + Validate(fileName); } - [Fact] public void AddWorksheetToWorkbook() { var wb = GetSimpleWorkbookDfn(); - + var fileName = Path.Combine(TempDir, "AddWorksheetToWorkbook.xlsx"); using (var stream = File.Open(fileName, FileMode.OpenOrCreate)) wb.WriteTo(stream); @@ -430,17 +361,15 @@ public void AddWorksheetToWorkbook() Validate(fileName); } - + private void Validate(string fileName) { using var sDoc = SpreadsheetDocument.Open(fileName, false); Validate(sDoc, s_spreadsheetExpectedErrors); } - private static readonly List s_spreadsheetExpectedErrors = new() - { - "The attribute 't' has invalid value 'd'. The Enumeration constraint failed.", - }; + private static readonly List s_spreadsheetExpectedErrors = + new() { "The attribute 't' has invalid value 'd'. The Enumeration constraint failed." }; } } diff --git a/Clippit.Tests/Html/HtmlToWmlConverterTests.cs b/Clippit.Tests/Html/HtmlToWmlConverterTests.cs index e1c04c21..2d45a91c 100644 --- a/Clippit.Tests/Html/HtmlToWmlConverterTests.cs +++ b/Clippit.Tests/Html/HtmlToWmlConverterTests.cs @@ -10,22 +10,21 @@ using DocumentFormat.OpenXml.Validation; using Xunit; using Xunit.Abstractions; - /******************************************************************************************* * HtmlToWmlConverter expects the HTML to be passed as an XElement, i.e. as XML. While the HTML test files that * are included in Open-Xml-PowerTools are able to be read as XML, most HTML is not able to be read as XML. * The best solution is to use the HtmlAgilityPack, which can parse HTML and save as XML. The HtmlAgilityPack * is licensed under the Ms-PL (same as Open-Xml-PowerTools) so it is convenient to include it in your solution, * and thereby you can convert HTML to XML that can be processed by the HtmlToWmlConverter. - * + * * A convenient way to get the DLL that has been checked out with HtmlToWmlConverter is to clone the repo at * https://github.com/EricWhiteDev/HtmlAgilityPack - * + * * That repo contains only the DLL that has been checked out with HtmlToWmlConverter. - * + * * Of course, you can also get the HtmlAgilityPack source and compile it to get the DLL. You can find it at * http://codeplex.com/HtmlAgilityPack - * + * * We don't include the HtmlAgilityPack in Open-Xml-PowerTools, to simplify installation. The XUnit tests in * this module do not require the HtmlAgilityPack to run. *******************************************************************************************/ @@ -40,9 +39,8 @@ namespace Clippit.Tests.Html { public class HtmlToWmlConverterTests : TestsBase { - public HtmlToWmlConverterTests(ITestOutputHelper log) : base(log) - { - } + public HtmlToWmlConverterTests(ITestOutputHelper log) + : base(log) { } private static readonly bool s_ProduceAnnotatedHtml = true; @@ -282,7 +280,6 @@ public HtmlToWmlConverterTests(ITestOutputHelper log) : base(log) [InlineData("T1850.html")] [InlineData("T1860.html")] [InlineData("T1870.html")] - public void HW001(string name) { #if false @@ -307,13 +304,21 @@ public void HW001(string name) var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceHtmlFi = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceImageDi = new DirectoryInfo(Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files"))); + var sourceImageDi = new DirectoryInfo( + Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files")) + ); var destImageDi = new DirectoryInfo(Path.Combine(TempDir, sourceImageDi.Name)); - var sourceCopiedToDestHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html"))); + var sourceCopiedToDestHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html")) + ); var destCssFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-2.css"))); - var destDocxFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx"))); - var annotatedHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt"))); + var destDocxFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx")) + ); + var annotatedHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt")) + ); if (!sourceCopiedToDestHtmlFi.Exists) { @@ -341,7 +346,9 @@ public void HW001(string name) } } - var usedAuthorCss = HtmlToWmlConverter.CleanUpCss((string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style")); + var usedAuthorCss = HtmlToWmlConverter.CleanUpCss( + (string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style") + ); File.WriteAllText(destCssFi.FullName, usedAuthorCss); if (cssFilter != null && cssFilter.Any()) @@ -377,14 +384,26 @@ public void HW001(string name) // that contains the HTML files settings.BaseUriForImages = Path.Combine(TempDir); - var doc = HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings, null, s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null); + var doc = HtmlToWmlConverter.ConvertHtmlToWml( + defaultCss, + usedAuthorCss, + userCss, + html, + settings, + null, + s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null + ); Assert.NotNull(doc); if (doc != null) SaveValidateAndFormatMainDocPart(destDocxFi, doc); #if DO_CONVERSION_VIA_WORD - var newAltChunkBeforeFi = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, name.Replace(".html", "-5-AltChunkBefore.docx"))); - var newAltChunkAfterFi = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, name.Replace(".html", "-6-ConvertedViaWord.docx"))); + var newAltChunkBeforeFi = new FileInfo( + Path.Combine(TestUtil.TempDir.FullName, name.Replace(".html", "-5-AltChunkBefore.docx")) + ); + var newAltChunkAfterFi = new FileInfo( + Path.Combine(TestUtil.TempDir.FullName, name.Replace(".html", "-6-ConvertedViaWord.docx")) + ); WordAutomationUtilities.DoConversionViaWord(newAltChunkBeforeFi, newAltChunkAfterFi, html); #endif } @@ -394,27 +413,47 @@ public void HW001(string name) [InlineData("E0020.html")] public void HW004(string name) { - var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceHtmlFi = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceImageDi = new DirectoryInfo(Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files"))); + var sourceImageDi = new DirectoryInfo( + Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files")) + ); var destImageDi = new DirectoryInfo(Path.Combine(TempDir, sourceImageDi.Name)); - var sourceCopiedToDestHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html"))); + var sourceCopiedToDestHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html")) + ); var destCssFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-2.css"))); - var destDocxFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx"))); - var annotatedHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt"))); + var destDocxFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx")) + ); + var annotatedHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt")) + ); File.Copy(sourceHtmlFi.FullName, sourceCopiedToDestHtmlFi.FullName); var html = HtmlToWmlReadAsXElement.ReadAsXElement(sourceCopiedToDestHtmlFi); - var usedAuthorCss = HtmlToWmlConverter.CleanUpCss((string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style")); + var usedAuthorCss = HtmlToWmlConverter.CleanUpCss( + (string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style") + ); File.WriteAllText(destCssFi.FullName, usedAuthorCss); var settings = HtmlToWmlConverter.GetDefaultSettings(); settings.BaseUriForImages = Path.Combine(TempDir); - Assert.Throws(() => HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings, null, s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null)); + Assert.Throws( + () => + HtmlToWmlConverter.ConvertHtmlToWml( + defaultCss, + usedAuthorCss, + userCss, + html, + settings, + null, + s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null + ) + ); } [Theory] @@ -423,24 +462,42 @@ public void TestingNestedRowspan(string name) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceHtmlFi = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var sourceImageDi = new DirectoryInfo(Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files"))); + var sourceImageDi = new DirectoryInfo( + Path.Combine(sourceDir.FullName, sourceHtmlFi.Name.Replace(".html", "_files")) + ); var destImageDi = new DirectoryInfo(Path.Combine(TempDir, sourceImageDi.Name)); - var sourceCopiedToDestHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html"))); + var sourceCopiedToDestHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-1-Source.html")) + ); var destCssFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-2.css"))); - var destDocxFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx"))); - var annotatedHtmlFi = new FileInfo(Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt"))); + var destDocxFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx")) + ); + var annotatedHtmlFi = new FileInfo( + Path.Combine(TempDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt")) + ); File.Copy(sourceHtmlFi.FullName, sourceCopiedToDestHtmlFi.FullName); var html = HtmlToWmlReadAsXElement.ReadAsXElement(sourceCopiedToDestHtmlFi); - var usedAuthorCss = HtmlToWmlConverter.CleanUpCss((string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style")); + var usedAuthorCss = HtmlToWmlConverter.CleanUpCss( + (string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style") + ); File.WriteAllText(destCssFi.FullName, usedAuthorCss); var settings = HtmlToWmlConverter.GetDefaultSettings(); settings.BaseUriForImages = Path.Combine(TempDir); - var doc = HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings, null, s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null); + var doc = HtmlToWmlConverter.ConvertHtmlToWml( + defaultCss, + usedAuthorCss, + userCss, + html, + settings, + null, + s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null + ); Assert.NotNull(doc); if (doc != null) @@ -461,9 +518,7 @@ private static void SaveValidateAndFormatMainDocPart(FileInfo destDocxFi, WmlDoc document.MainDocumentPart.PutXDocumentWithFormatting(); var validator = new OpenXmlValidator(); var errors = validator.Validate(document); - var errorsString = errors - .Select(e => e.Description + Environment.NewLine) - .StringConcatenate(); + var errorsString = errors.Select(e => e.Description + Environment.NewLine).StringConcatenate(); // Assert that there were no errors in the generated document. Assert.Equal("", errorsString); @@ -548,7 +603,6 @@ private static void SaveValidateAndFormatMainDocPart(FileInfo destDocxFi, WmlDoc "; private static readonly string userCss = @""; - } } diff --git a/Clippit.Tests/Html/HtmlToWmlReadAsXElement.cs b/Clippit.Tests/Html/HtmlToWmlReadAsXElement.cs index 2a7178aa..9ee94538 100644 --- a/Clippit.Tests/Html/HtmlToWmlReadAsXElement.cs +++ b/Clippit.Tests/Html/HtmlToWmlReadAsXElement.cs @@ -5,25 +5,24 @@ using System.Linq; using System.Xml; using System.Xml.Linq; - /******************************************************************************************* * HtmlToWmlConverter expects the HTML to be passed as an XElement, i.e. as XML. While the HTML test files that * are included in Open-Xml-PowerTools are able to be read as XML, most HTML is not able to be read as XML. * The best solution is to use the HtmlAgilityPack, which can parse HTML and save as XML. The HtmlAgilityPack * is licensed under the Ms-PL (same as Open-Xml-PowerTools) so it is convenient to include it in your solution, * and thereby you can convert HTML to XML that can be processed by the HtmlToWmlConverter. - * + * * A convenient way to get the DLL that has been checked out with HtmlToWmlConverter is to clone the repo at * https://github.com/EricWhiteDev/HtmlAgilityPack - * + * * That repo contains only the DLL that has been checked out with HtmlToWmlConverter. - * + * * Of course, you can also get the HtmlAgilityPack source and compile it to get the DLL. You can find it at * http://codeplex.com/HtmlAgilityPack - * + * * We don't include the HtmlAgilityPack in Open-Xml-PowerTools, to simplify installation. The XUnit tests in * this module do not require the HtmlAgilityPack to run. -*******************************************************************************************/ +*******************************************************************************************/ #if USE_HTMLAGILITYPACK using HtmlAgilityPack; @@ -77,9 +76,11 @@ private static object ConvertToNoNamespace(XNode node) var element = node as XElement; if (element != null) { - return new XElement(element.Name.LocalName, + return new XElement( + element.Name.LocalName, element.Attributes().Where(a => !a.IsNamespaceDeclaration), - element.Nodes().Select(n => ConvertToNoNamespace(n))); + element.Nodes().Select(n => ConvertToNoNamespace(n)) + ); } return node; } diff --git a/Clippit.Tests/Html/Samples/HtmlConverterSamples.cs b/Clippit.Tests/Html/Samples/HtmlConverterSamples.cs index e19fcb63..4368835f 100644 --- a/Clippit.Tests/Html/Samples/HtmlConverterSamples.cs +++ b/Clippit.Tests/Html/Samples/HtmlConverterSamples.cs @@ -9,24 +9,23 @@ namespace Clippit.Tests.Html.Samples { - /*************************************************************************** - * IMPORTANT NOTE: - * - * With versions 4.1 and later, the name of the HtmlConverter class has been - * changed to WmlToHtmlConverter, to make it orthogonal with HtmlToWmlConverter. - * - * There are thin wrapper classes, HtmlConverter, and HtmlConverterSettings, - * which maintain backwards compat for code that uses the old name. - * - * Other than the name change of the classes themselves, the functionality - * in WmlToHtmlConverter is identical to the old HtmlConverter class. - ***************************************************************************/ + /*************************************************************************** + * IMPORTANT NOTE: + * + * With versions 4.1 and later, the name of the HtmlConverter class has been + * changed to WmlToHtmlConverter, to make it orthogonal with HtmlToWmlConverter. + * + * There are thin wrapper classes, HtmlConverter, and HtmlConverterSettings, + * which maintain backwards compat for code that uses the old name. + * + * Other than the name change of the classes themselves, the functionality + * in WmlToHtmlConverter is identical to the old HtmlConverter class. + ***************************************************************************/ public class HtmlConverterSamples : TestsBase { - public HtmlConverterSamples(ITestOutputHelper log) : base(log) - { - } + public HtmlConverterSamples(ITestOutputHelper log) + : base(log) { } [Theory] [InlineData("5DayTourPlanTemplate.docx")] @@ -55,8 +54,7 @@ public void ConvertToHtml(string fileName) var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html")); destFileName = new FileInfo(Path.Combine(TempDir, destFileName.Name)); - var imageDirectoryName = - destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files"; + var imageDirectoryName = destFileName.FullName.Substring(0, destFileName.FullName.Length - 5) + "_files"; var imageCounter = 0; var pageTitle = fi.FullName; @@ -79,15 +77,13 @@ public void ConvertToHtml(string fileName) { ++imageCounter; return ImageHelper.DefaultImageHandler(imageInfo, imageDirectoryName, imageCounter); - } + }, }; var htmlElement = HtmlConverter.ConvertToHtml(wDoc, settings); // Produce HTML document with declaration to tell the browser // we are using HTML5. - var html = new XDocument( - new XDocumentType("html", null, null, null), - htmlElement); + var html = new XDocument(new XDocumentType("html", null, null, null), htmlElement); // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type // XEntity. PtOpenXmlUtil.cs define the XEntity class. See diff --git a/Clippit.Tests/Html/Samples/HtmlToWmlConverterSamples.cs b/Clippit.Tests/Html/Samples/HtmlToWmlConverterSamples.cs index 8953874a..ccfbdf9b 100644 --- a/Clippit.Tests/Html/Samples/HtmlToWmlConverterSamples.cs +++ b/Clippit.Tests/Html/Samples/HtmlToWmlConverterSamples.cs @@ -13,9 +13,8 @@ namespace Clippit.Tests.Html.Samples { public class HtmlToWmlConverterSamples : TestsBase { - public HtmlToWmlConverterSamples(ITestOutputHelper log) : base(log) - { - } + public HtmlToWmlConverterSamples(ITestOutputHelper log) + : base(log) { } private static string GetFilePath(string path) => Path.Combine("../../../Html/Samples/HtmlToWmlConverter/", path); @@ -72,16 +71,18 @@ private void ConvertToDocx(string file, string destinationDir) var sourceImageDi = new DirectoryInfo(destinationDir); var destCssFi = new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-2.css"))); - var destDocxFi = new FileInfo(Path.Combine(destinationDir, - sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx"))); - var annotatedHtmlFi = - new FileInfo(Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt"))); + var destDocxFi = new FileInfo( + Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-3-ConvertedByHtmlToWml.docx")) + ); + var annotatedHtmlFi = new FileInfo( + Path.Combine(destinationDir, sourceHtmlFi.Name.Replace(".html", "-4-Annotated.txt")) + ); var html = HtmlToWmlReadAsXElement.ReadAsXElement(sourceHtmlFi); - var usedAuthorCss = - HtmlToWmlConverter.CleanUpCss((string)html.Descendants() - .FirstOrDefault(d => d.Name.LocalName.ToLower() == "style")); + var usedAuthorCss = HtmlToWmlConverter.CleanUpCss( + (string)html.Descendants().FirstOrDefault(d => d.Name.LocalName.ToLower() == "style") + ); File.WriteAllText(destCssFi.FullName, usedAuthorCss); var settings = HtmlToWmlConverter.GetDefaultSettings(); @@ -89,8 +90,15 @@ private void ConvertToDocx(string file, string destinationDir) // that contains the HTML files settings.BaseUriForImages = sourceHtmlFi.DirectoryName; - var doc = HtmlToWmlConverter.ConvertHtmlToWml(defaultCss, usedAuthorCss, userCss, html, settings, null, - s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null); + var doc = HtmlToWmlConverter.ConvertHtmlToWml( + defaultCss, + usedAuthorCss, + userCss, + html, + settings, + null, + s_ProduceAnnotatedHtml ? annotatedHtmlFi.FullName : null + ); doc.SaveAs(destDocxFi.FullName); } @@ -169,8 +177,9 @@ private void ConvertToDocx(string file, string destinationDir) "; private static readonly string userCss = @""; - - private static readonly string[] s_productNames = { + + private static readonly string[] s_productNames = + { "Unicycle", "Bicycle", "Tricycle", @@ -185,20 +194,24 @@ private static XElement GenerateDataFromDataSource(FileInfo dataFi, int numberOf var r = new Random(); for (var i = 0; i < numberOfDocumentsToGenerate; ++i) { - var customer = new XElement("Customer", + var customer = new XElement( + "Customer", new XElement("CustomerID", i + 1), new XElement("Name", "Eric White"), new XElement("HighValueCustomer", r.Next(2) == 0 ? "True" : "False"), - new XElement("Orders")); + new XElement("Orders") + ); var orders = customer.Element("Orders"); var numberOfOrders = r.Next(10) + 1; for (var j = 0; j < numberOfOrders; j++) { - var order = new XElement("Order", + var order = new XElement( + "Order", new XAttribute("Number", j + 1), new XElement("ProductDescription", s_productNames[r.Next(s_productNames.Length)]), new XElement("Quantity", r.Next(10)), - new XElement("OrderDate", "September 26, 2015")); + new XElement("OrderDate", "September 26, 2015") + ); orders.Add(order); } customers.Add(customer); @@ -206,7 +219,7 @@ private static XElement GenerateDataFromDataSource(FileInfo dataFi, int numberOf customers.Save(dataFi.FullName); return customers; } - + public static FileInfo ConvertToHtml(string file, string outputDirectory) { var fi = new FileInfo(file); @@ -240,15 +253,13 @@ public static FileInfo ConvertToHtml(string file, string outputDirectory) { ++imageCounter; return ImageHelper.DefaultImageHandler(imageInfo, imageDirectoryName, imageCounter); - } + }, }; var htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); // Produce HTML document with declaration to tell the browser // we are using HTML5. - var html = new XDocument( - new XDocumentType("html", null, null, null), - htmlElement); + var html = new XDocument(new XDocumentType("html", null, null, null), htmlElement); // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type // XEntity. PtOpenXmlUtil.cs define the XEntity class. See diff --git a/Clippit.Tests/PowerPoint/OpenXmlExtensions.cs b/Clippit.Tests/PowerPoint/OpenXmlExtensions.cs index b3d05a27..157a00e9 100644 --- a/Clippit.Tests/PowerPoint/OpenXmlExtensions.cs +++ b/Clippit.Tests/PowerPoint/OpenXmlExtensions.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Xml; using System.Xml.Linq; - using DocumentFormat.OpenXml.Packaging; namespace Clippit.Tests.PowerPoint @@ -52,7 +51,7 @@ private static void FixInvalidUri(Stream fs) .Where(r => r.Attribute("TargetMode")?.Value == "External"); foreach (var rel in urisToCheck) { - if (rel.Attribute("Target") is {} attr) + if (rel.Attribute("Target") is { } attr) { try { diff --git a/Clippit.Tests/PowerPoint/PresentationBuilderSlidePublishingTests.cs b/Clippit.Tests/PowerPoint/PresentationBuilderSlidePublishingTests.cs index 14fb35fe..78c4dd28 100644 --- a/Clippit.Tests/PowerPoint/PresentationBuilderSlidePublishingTests.cs +++ b/Clippit.Tests/PowerPoint/PresentationBuilderSlidePublishingTests.cs @@ -16,10 +16,11 @@ public class PresentationBuilderSlidePublishingTests : TestsBase public static IEnumerable GetData() { var files = Directory.GetFiles(SourceDirectory, "*.pptx", SearchOption.TopDirectoryOnly); - return files.OrderBy(x=>x).Select(path => new[] {path}); + return files.OrderBy(x => x).Select(path => new[] { path }); } - public PresentationBuilderSlidePublishingTests(ITestOutputHelper log): base(log) + public PresentationBuilderSlidePublishingTests(ITestOutputHelper log) + : base(log) { if (!Directory.Exists(TargetDirectory)) Directory.CreateDirectory(TargetDirectory); @@ -35,7 +36,7 @@ public void PublishUsingPublishSlides(string sourcePath) Directory.CreateDirectory(targetDir); using var srcStream = File.Open(sourcePath, FileMode.Open); - var openSettings = new OpenSettings {AutoSave = false}; + var openSettings = new OpenSettings { AutoSave = false }; using var srcDoc = OpenXmlExtensions.OpenPresentation(srcStream, false, openSettings); var title = srcDoc.PackageProperties.Title ?? string.Empty; @@ -47,14 +48,14 @@ public void PublishUsingPublishSlides(string sourcePath) slide.SaveAs(Path.Combine(targetDir, Path.GetFileName(slide.FileName))); using var streamDoc = new OpenXmlMemoryStreamDocument(slide); - using var slideDoc = streamDoc.GetPresentationDocument(new OpenSettings {AutoSave = false}); + using var slideDoc = streamDoc.GetPresentationDocument(new OpenSettings { AutoSave = false }); Assert.Equal(modified, slideDoc.PackageProperties.Modified); if (title.Equals(slideDoc.PackageProperties.Title)) sameTitle++; } - Assert.InRange(sameTitle, 0,4); + Assert.InRange(sameTitle, 0, 4); } [Theory] @@ -76,24 +77,24 @@ public void ExtractSlideWithExtendedChart() { var sourcePath = Path.Combine(SourceDirectory, "SlideWithExtendedChart.pptx"); using var srcStream = File.Open(sourcePath, FileMode.Open); - var openSettings = new OpenSettings {AutoSave = false}; + var openSettings = new OpenSettings { AutoSave = false }; using var srcDoc = OpenXmlExtensions.OpenPresentation(srcStream, false, openSettings); - - var srcEmbeddingCount = srcDoc.PresentationPart.SlideParts - .SelectMany(slide => slide.ExtendedChartParts) + + var srcEmbeddingCount = srcDoc + .PresentationPart.SlideParts.SelectMany(slide => slide.ExtendedChartParts) .Count(); Assert.Equal(1, srcEmbeddingCount); - + var slide = PresentationBuilder.PublishSlides(srcDoc, Path.GetFileName(sourcePath)).First(); using var streamDoc = new OpenXmlMemoryStreamDocument(slide); using var slideDoc = streamDoc.GetPresentationDocument(openSettings); - var slideEmbeddingCount = slideDoc.PresentationPart.SlideParts - .Select(slide => slide.ExtendedChartParts) - .Count(); + var slideEmbeddingCount = slideDoc + .PresentationPart.SlideParts.Select(slide => slide.ExtendedChartParts) + .Count(); Assert.Equal(srcEmbeddingCount, slideEmbeddingCount); } - + [Theory] [InlineData("BRK3066.pptx")] public void ReassemblePresentation(string fileName) @@ -110,7 +111,7 @@ public void ReassemblePresentation(string fileName) newDocument.SaveAs(Path.Combine(TargetDirectory, newDocument.FileName)); var baseSize = document.DocumentByteArray.Length; - Assert.InRange(newDocument.DocumentByteArray.Length, 0.3 * baseSize, 1.1* baseSize); + Assert.InRange(newDocument.DocumentByteArray.Length, 0.3 * baseSize, 1.1 * baseSize); } [Theory] @@ -125,10 +126,7 @@ public void ExtractMasters(string fileName) numberOfMasters = doc1.PresentationPart.SlideMasterParts.Count(); } - - var onlyMaster = - PresentationBuilder.BuildPresentation( - new List {new(source, 0, 0, true)}); + var onlyMaster = PresentationBuilder.BuildPresentation(new List { new(source, 0, 0, true) }); onlyMaster.FileName = fileName.Replace(".pptx", "_masterOnly.pptx"); onlyMaster.SaveAs(Path.Combine(TargetDirectory, onlyMaster.FileName)); @@ -149,13 +147,14 @@ public void ReassemblePresentationWithMaster(string fileName) // generate presentation with all masters var onlyMaster = PresentationBuilder.BuildPresentation( - new List {new(presentation, 0, 0, true)}); + new List { new(presentation, 0, 0, true) } + ); // publish slides with one-layout masters var slides = PresentationBuilder.PublishSlides(presentation); // compose them together using only master as the first source - var sources = new List {new(onlyMaster, true)}; + var sources = new List { new(onlyMaster, true) }; sources.AddRange(slides.Select(x => new SlideSource(x, false))); var newDocument = PresentationBuilder.BuildPresentation(sources); @@ -176,9 +175,7 @@ public void MergeAllPowerPoints() .Cast() .ToList(); - var sources = files - .Select(x => new SlideSource(x, 0, 1000, true)) - .ToList(); + var sources = files.Select(x => new SlideSource(x, 0, 1000, true)).ToList(); var result = PresentationBuilder.BuildPresentation(sources); var resultFile = Path.Combine(TempDir, "MergedDeck.pptx"); diff --git a/Clippit.Tests/PowerPoint/PresentationBuilderTests.cs b/Clippit.Tests/PowerPoint/PresentationBuilderTests.cs index f649bb42..093a805d 100644 --- a/Clippit.Tests/PowerPoint/PresentationBuilderTests.cs +++ b/Clippit.Tests/PowerPoint/PresentationBuilderTests.cs @@ -15,10 +15,9 @@ namespace Clippit.Tests.PowerPoint { public class PresentationBuilderTests : TestsBase { - public PresentationBuilderTests(ITestOutputHelper log) : base(log) - { - } - + public PresentationBuilderTests(ITestOutputHelper log) + : base(log) { } + [Fact] public void PB001_Formatting() { @@ -44,10 +43,7 @@ public void PB002_Formatting() var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var source2Pptx = new FileInfo(Path.Combine(sourceDir.FullName, name2)); - var sources = new List - { - new(new PmlDocument(source2Pptx.FullName), 0, true), - }; + var sources = new List { new(new PmlDocument(source2Pptx.FullName), 0, true) }; var processedDestPptx = new FileInfo(Path.Combine(TempDir, "PB002-Formatting.pptx")); PresentationBuilder.BuildPresentation(sources).SaveAs(processedDestPptx.FullName); } @@ -116,10 +112,7 @@ public void PB006_VideoFormats() var oldMediaDataContentTypes = GetMediaDataContentTypes(sourcePptx); - var sources = new List - { - new(new PmlDocument(sourcePptx.FullName), true), - }; + var sources = new List { new(new PmlDocument(sourcePptx.FullName), true) }; var processedDestPptx = new FileInfo(Path.Combine(TempDir, "PB006-Videos.pptx")); PresentationBuilder.BuildPresentation(sources).SaveAs(processedDestPptx.FullName); @@ -131,8 +124,10 @@ public void PB006_VideoFormats() private static string[] GetMediaDataContentTypes(FileInfo fi) { using var ptDoc = PresentationDocument.Open(fi.FullName, false); - return ptDoc.PresentationPart.SlideParts.SelectMany( - p => p.DataPartReferenceRelationships.Select(d => d.DataPart.ContentType)) + return ptDoc + .PresentationPart.SlideParts.SelectMany(p => + p.DataPartReferenceRelationships.Select(d => d.DataPart.ContentType) + ) .Distinct() .OrderBy(m => m) .ToArray(); diff --git a/Clippit.Tests/PowerPoint/PtUtilTests.cs b/Clippit.Tests/PowerPoint/PtUtilTests.cs index 084d2232..07cccf8b 100644 --- a/Clippit.Tests/PowerPoint/PtUtilTests.cs +++ b/Clippit.Tests/PowerPoint/PtUtilTests.cs @@ -23,7 +23,6 @@ public void PU001(string name) Assert.True(p.Parts.Length != 0); Assert.DoesNotContain(p.Parts, part => part.ContentType == null || part.ContentLocation == null); } - } } diff --git a/Clippit.Tests/PowerPoint/Samples/PresentationBuilderSamples.cs b/Clippit.Tests/PowerPoint/Samples/PresentationBuilderSamples.cs index ae7a6f50..e62476e9 100644 --- a/Clippit.Tests/PowerPoint/Samples/PresentationBuilderSamples.cs +++ b/Clippit.Tests/PowerPoint/Samples/PresentationBuilderSamples.cs @@ -11,10 +11,9 @@ namespace Clippit.Tests.PowerPoint.Samples { public class PresentationBuilderSamples : TestsBase { - public PresentationBuilderSamples(ITestOutputHelper log) : base(log) - { - } - + public PresentationBuilderSamples(ITestOutputHelper log) + : base(log) { } + private static string GetFilePath(string path) => Path.Combine("../../../PowerPoint/Samples/PresentationBuilder/", path); @@ -34,18 +33,18 @@ public void Sample1() var sourceDoc = new PmlDocument(source1); var sources = new List { - new(sourceDoc, 0, 1, false), // Title - new(sourceDoc, 1, 1, false), // First intro (of 3) - new(sourceDoc, 4, 2, false), // Sales bios - new(sourceDoc, 9, 3, false), // Content slides - new(sourceDoc, 13, 1, false), // Closing summary + new(sourceDoc, 0, 1, false), // Title + new(sourceDoc, 1, 1, false), // First intro (of 3) + new(sourceDoc, 4, 2, false), // Sales bios + new(sourceDoc, 9, 3, false), // Content slides + new(sourceDoc, 13, 1, false), // Closing summary }; PresentationBuilder.BuildPresentation(sources).SaveAs(Path.Combine(TempDir, "Out1.pptx")); sources = new List { - new(new PmlDocument(source2), 2, 1, true), // Choose company - new(new PmlDocument(source3), false), // Content + new(new PmlDocument(source2), 2, 1, true), // Choose company + new(new PmlDocument(source3), false), // Content }; PresentationBuilder.BuildPresentation(sources).SaveAs(Path.Combine(TempDir, "Out2.pptx")); diff --git a/Clippit.Tests/TestsBase.cs b/Clippit.Tests/TestsBase.cs index c8463411..2daec69c 100644 --- a/Clippit.Tests/TestsBase.cs +++ b/Clippit.Tests/TestsBase.cs @@ -35,25 +35,29 @@ public TestsBase(ITestOutputHelper log) protected readonly ITestOutputHelper Log; private readonly OpenXmlValidator _validator; - private static readonly Lazy s_tempDir = new(() => - { - var dir = new DirectoryInfo("./../../../../temp"); - if (dir.Exists) - dir.Delete(true); - dir.Create(); - return dir.FullName; - }); + private static readonly Lazy s_tempDir = + new(() => + { + var dir = new DirectoryInfo("./../../../../temp"); + if (dir.Exists) + dir.Delete(true); + dir.Create(); + return dir.FullName; + }); protected static string TempDir => s_tempDir.Value; protected void Validate(OpenXmlPackage package, List expectedErrors) { - var errors = _validator.Validate(package).Where(ve => - { - var found = expectedErrors.Any(xe => ve.Description.Contains(xe)); - return !found; - }).ToList(); - + var errors = _validator + .Validate(package) + .Where(ve => + { + var found = expectedErrors.Any(xe => ve.Description.Contains(xe)); + return !found; + }) + .ToList(); + foreach (var item in errors) { Log.WriteLine(item.Description); @@ -68,19 +72,19 @@ protected void ValidateUniqueDocPrIds(FileInfo fi) var docPrIds = new HashSet(); foreach (var item in doc.MainDocumentPart.GetXDocument().Descendants(WP.docPr)) Assert.True(docPrIds.Add(item.Attribute(NoNamespace.id).Value)); - + foreach (var header in doc.MainDocumentPart.HeaderParts) foreach (var item in header.GetXDocument().Descendants(WP.docPr)) Assert.True(docPrIds.Add(item.Attribute(NoNamespace.id).Value)); - + foreach (var footer in doc.MainDocumentPart.FooterParts) foreach (var item in footer.GetXDocument().Descendants(WP.docPr)) Assert.True(docPrIds.Add(item.Attribute(NoNamespace.id).Value)); - + if (doc.MainDocumentPart.FootnotesPart is not null) foreach (var item in doc.MainDocumentPart.FootnotesPart.GetXDocument().Descendants(WP.docPr)) Assert.True(docPrIds.Add(item.Attribute(NoNamespace.id).Value)); - + if (doc.MainDocumentPart.EndnotesPart is not null) foreach (var item in doc.MainDocumentPart.EndnotesPart.GetXDocument().Descendants(WP.docPr)) Assert.True(docPrIds.Add(item.Attribute(NoNamespace.id).Value)); diff --git a/Clippit.Tests/Word/DocumentAssemblerTests.cs b/Clippit.Tests/Word/DocumentAssemblerTests.cs index 95c64640..da5c92f7 100644 --- a/Clippit.Tests/Word/DocumentAssemblerTests.cs +++ b/Clippit.Tests/Word/DocumentAssemblerTests.cs @@ -17,7 +17,8 @@ namespace Clippit.Tests.Word { public class DocumentAssemblerTests : TestsBase { - public DocumentAssemblerTests(ITestOutputHelper log) : base(log) + public DocumentAssemblerTests(ITestOutputHelper log) + : base(log) { _sourceDir = new DirectoryInfo("../../../../TestFiles/DA/"); } @@ -59,11 +60,9 @@ public DocumentAssemblerTests(ITestOutputHelper log) : base(log) [InlineData("DA034-HeaderFooter.docx", "DA-Data.xml", false)] [InlineData("DA035-SchemaErrorInRepeat.docx", "DA-Data.xml", true)] [InlineData("DA036-SchemaErrorInConditional.docx", "DA-Data.xml", true)] - [InlineData("DA100-TemplateDocument.docx", "DA-Data.xml", false)] [InlineData("DA101-TemplateDocument.docx", "DA-Data.xml", true)] [InlineData("DA102-TemplateDocument.docx", "DA-Data.xml", true)] - [InlineData("DA201-TemplateDocument.docx", "DA-Data.xml", false)] [InlineData("DA202-TemplateDocument.docx", "DA-DataNotHighValueCust.xml", false)] [InlineData("DA203-Select-XPathFindsNoData.docx", "DA-Data.xml", true)] @@ -100,7 +99,6 @@ public DocumentAssemblerTests(ITestOutputHelper log) : base(log) [InlineData("DA237-SchemaErrorInRepeat.docx", "DA-Data.xml", true)] [InlineData("DA238-SchemaErrorInConditional.docx", "DA-Data.xml", true)] [InlineData("DA239-RunLevelCC-Repeat.docx", "DA-Data.xml", false)] - [InlineData("DA250-ConditionalWithRichXPath.docx", "DA250-Address.xml", false)] [InlineData("DA251-EnhancedTables.docx", "DA-Data.xml", false)] [InlineData("DA252-Table-With-Sum.docx", "DA-Data.xml", false)] @@ -155,7 +153,6 @@ public DocumentAssemblerTests(ITestOutputHelper log) : base(log) [InlineData("DA284A-ImageSelectWithHeaderAndFooter.docx", "DA-Data-WithImages.xml", false)] [InlineData("DA285-ImageSelectNoParagraphFollowedAfterMetadata.docx", "DA-Data-WithImages.xml", true)] [InlineData("DA285A-ImageSelectNoParagraphFollowedAfterMetadata.docx", "DA-Data-WithImages.xml", true)] - [InlineData("DA-I0038-TemplateWithMultipleXPathResults.docx", "DA-I0038-Data.xml", false)] public void DA101(string name, string data, bool err) { @@ -165,8 +162,14 @@ public void DA101(string name, string data, bool err) var wmlTemplate = new WmlDocument(templateDocx.FullName); var xmlData = XElement.Load(dataFile.FullName); - var afterAssembling = DocumentAssembler.AssembleDocument(wmlTemplate, xmlData, out var returnedTemplateError); - var assembledDocx = new FileInfo(Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx"))); + var afterAssembling = DocumentAssembler.AssembleDocument( + wmlTemplate, + xmlData, + out var returnedTemplateError + ); + var assembledDocx = new FileInfo( + Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx")) + ); afterAssembling.SaveAs(assembledDocx.FullName); Validate(assembledDocx); @@ -178,13 +181,17 @@ public void DA101(string name, string data, bool err) public void DA259(string name, string data, bool err) { DA101(name, data, err); - var assembledDocx = new FileInfo(Path.Combine(TempDir, name.Replace(".docx", "-processed-by-DocumentAssembler.docx"))); + var assembledDocx = new FileInfo( + Path.Combine(TempDir, name.Replace(".docx", "-processed-by-DocumentAssembler.docx")) + ); var afterAssembling = new WmlDocument(assembledDocx.FullName); - var brCount = afterAssembling.MainDocumentPart - .Element(W.body) - .Elements(W.p).ElementAt(1) - .Elements(W.r) - .Elements(W.br).Count(); + var brCount = afterAssembling + .MainDocumentPart.Element(W.body) + .Elements(W.p) + .ElementAt(1) + .Elements(W.r) + .Elements(W.br) + .Count(); Assert.Equal(4, brCount); } @@ -200,9 +207,13 @@ public void DA102_Throws(string name, string data) WmlDocument afterAssembling; Assert.Throws(() => - { - afterAssembling = DocumentAssembler.AssembleDocument(wmlTemplate, xmldata, out var returnedTemplateError); - }); + { + afterAssembling = DocumentAssembler.AssembleDocument( + wmlTemplate, + xmldata, + out var returnedTemplateError + ); + }); } [Theory] @@ -210,7 +221,9 @@ public void DA102_Throws(string name, string data) public void DATemplateMaior(string name, string data, bool err) { DA101(name, data, err); - var assembledDocx = new FileInfo(Path.Combine(TempDir, name.Replace(".docx", "-processed-by-DocumentAssembler.docx"))); + var assembledDocx = new FileInfo( + Path.Combine(TempDir, name.Replace(".docx", "-processed-by-DocumentAssembler.docx")) + ); var afterAssembling = new WmlDocument(assembledDocx.FullName); var descendants = afterAssembling.MainDocumentPart.Value; @@ -222,19 +235,23 @@ public void DATemplateMaior(string name, string data, bool err) [InlineData("DA-xmlerror.docx", "DA-xmlerror.xml")] public void DAXmlError(string name, string data) { - var templateDocx = new FileInfo(Path.Combine(_sourceDir.FullName, name)); var dataFile = new FileInfo(Path.Combine(_sourceDir.FullName, data)); var wmlTemplate = new WmlDocument(templateDocx.FullName); var xmlData = XElement.Load(dataFile.FullName); - var afterAssembling = DocumentAssembler.AssembleDocument(wmlTemplate, xmlData, out var returnedTemplateError); - var assembledDocx = new FileInfo(Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx"))); + var afterAssembling = DocumentAssembler.AssembleDocument( + wmlTemplate, + xmlData, + out var returnedTemplateError + ); + var assembledDocx = new FileInfo( + Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx")) + ); afterAssembling.SaveAs(assembledDocx.FullName); } - [Theory] [InlineData("DA025-TemplateDocument.docx", "DA-Data.xml", false)] public void DA103_UseXmlDocument(string name, string data, bool err) @@ -246,8 +263,14 @@ public void DA103_UseXmlDocument(string name, string data, bool err) var xmlData = new XmlDocument(); xmlData.Load(dataFile.FullName); - var afterAssembling = DocumentAssembler.AssembleDocument(wmlTemplate, xmlData, out var returnedTemplateError); - var assembledDocx = new FileInfo(Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx"))); + var afterAssembling = DocumentAssembler.AssembleDocument( + wmlTemplate, + xmlData, + out var returnedTemplateError + ); + var assembledDocx = new FileInfo( + Path.Combine(TempDir, templateDocx.Name.Replace(".docx", "-processed-by-DocumentAssembler.docx")) + ); afterAssembling.SaveAs(assembledDocx.FullName); Validate(assembledDocx); @@ -260,23 +283,24 @@ private void Validate(FileInfo fi) Validate(wDoc, s_expectedErrors); } - private static readonly List s_expectedErrors = new() - { - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenVBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowFirstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowLastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowFirstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowLastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noVBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddVBand' attribute is not declared.", - }; + private static readonly List s_expectedErrors = + new() + { + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenVBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowFirstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowLastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowFirstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowLastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noVBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddVBand' attribute is not declared.", + }; } } diff --git a/Clippit.Tests/Word/DocumentBuilderTests.cs b/Clippit.Tests/Word/DocumentBuilderTests.cs index 429f7491..56690569 100644 --- a/Clippit.Tests/Word/DocumentBuilderTests.cs +++ b/Clippit.Tests/Word/DocumentBuilderTests.cs @@ -16,24 +16,24 @@ namespace Clippit.Tests.Word { public class DocumentBuilderTests : TestsBase { - public DocumentBuilderTests(ITestOutputHelper log) : base(log) + public DocumentBuilderTests(ITestOutputHelper log) + : base(log) { _sourceDir = new DirectoryInfo("../../../../TestFiles/"); } private readonly DirectoryInfo _sourceDir; - + [Fact] public void DB001_DocumentBuilderKeepSections() { var name = "DB001-Sections.docx"; var sourceDocx = new FileInfo(Path.Combine(_sourceDir.FullName, name)); - var sources = new List - { - new Source(new WmlDocument(sourceDocx.FullName), true), - }; - var processedDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx"))); + var sources = new List { new Source(new WmlDocument(sourceDocx.FullName), true) }; + var processedDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx")) + ); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); } @@ -46,10 +46,16 @@ public void DB002_DocumentBuilderKeepSectionsDiscardHeaders() var sources = new List { new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, - new Source(new WmlDocument(source2Docx.FullName)) { KeepSections = true, DiscardHeadersAndFootersInKeptSections = true }, + new Source(new WmlDocument(source2Docx.FullName)) + { + KeepSections = true, + DiscardHeadersAndFootersInKeptSections = true, + }, new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, }; - var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB002-Keep-Sections-Discard-Headers-And-Footers.docx")); + var processedDestDocx = new FileInfo( + Path.Combine(TempDir, "DB002-Keep-Sections-Discard-Headers-And-Footers.docx") + ); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); } @@ -63,7 +69,11 @@ public void DB003_DocumentBuilderOnlyDefaultHeader() sources = new List { new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, - new Source(new WmlDocument(source2Docx.FullName)) { KeepSections = true, DiscardHeadersAndFootersInKeptSections = true }, + new Source(new WmlDocument(source2Docx.FullName)) + { + KeepSections = true, + DiscardHeadersAndFootersInKeptSections = true, + }, new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, }; var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB003-Only-Default-Header.docx")); @@ -79,10 +89,14 @@ public void DB004_DocumentBuilderNoHeaders() var sources = new List { new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, - new Source(new WmlDocument(source2Docx.FullName)) { KeepSections = true, DiscardHeadersAndFootersInKeptSections = true }, + new Source(new WmlDocument(source2Docx.FullName)) + { + KeepSections = true, + DiscardHeadersAndFootersInKeptSections = true, + }, new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, }; - + var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB003-Only-Default-Header.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); } @@ -96,7 +110,11 @@ public void DB005_HeadersWithRefsToImages() var sources = new List { new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, - new Source(new WmlDocument(source2Docx.FullName)) { KeepSections = true, DiscardHeadersAndFootersInKeptSections = true }, + new Source(new WmlDocument(source2Docx.FullName)) + { + KeepSections = true, + DiscardHeadersAndFootersInKeptSections = true, + }, new Source(new WmlDocument(source1Docx.FullName)) { KeepSections = true }, }; var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB005.docx")); @@ -111,10 +129,7 @@ public void DB006_Example_DocumentBuilder01() var source3 = new FileInfo(Path.Combine(_sourceDir.FullName, "DB006-Source3.docx")); // Create new document from 10 paragraphs starting at paragraph 5 of Source1.docx - var sources = new List - { - new Source(new WmlDocument(source1.FullName), 5, 10, true), - }; + var sources = new List { new Source(new WmlDocument(source1.FullName), 5, 10, true) }; var out1 = new FileInfo(Path.Combine(TempDir, "DB006-Out1.docx")); DocumentBuilder.BuildDocument(sources, out1.FullName); Validate(out1); @@ -163,8 +178,8 @@ public void DB006_Example_DocumentBuilder01() var wmlOut5 = DocumentBuilder.BuildDocument(sources); var out5 = new FileInfo(Path.Combine(TempDir, "DB006-Out5.docx")); - wmlOut5.SaveAs(out5.FullName); // save it to the file system, but we could just as easily done something - // else with it. + wmlOut5.SaveAs(out5.FullName); // save it to the file system, but we could just as easily done something + // else with it. Validate(out5); } @@ -199,25 +214,24 @@ public void DB008_DeleteParasWithGivenStyle() using (var doc = WordprocessingDocument.Open(notes.FullName, false)) { sources = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Select((p, i) => new - { - Paragraph = p, - Index = i, - }) - .GroupAdjacent(pi => (string)pi.Paragraph - .Elements(W.pPr) - .Elements(W.pStyle) - .Attributes(W.val) - .FirstOrDefault() != "Note") + .Select((p, i) => new { Paragraph = p, Index = i }) + .GroupAdjacent(pi => + (string)pi.Paragraph.Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault() + != "Note" + ) .Where(g => g.Key) - .Select(g => (ISource) new Source( - new WmlDocument(notes.FullName), g.First().Index, - g.Last().Index - g.First().Index + 1, true)) + .Select(g => + (ISource) + new Source( + new WmlDocument(notes.FullName), + g.First().Index, + g.Last().Index - g.First().Index + 1, + true + ) + ) .ToList(); } var newNotes = new FileInfo(Path.Combine(TempDir, "DB008-NewNotes.docx")); @@ -226,23 +240,87 @@ public void DB008_DeleteParasWithGivenStyle() } [Theory] - [InlineData("DB009-00010", "DB/HeadersFooters/Src/Content-Controls.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00020", "DB/HeadersFooters/Src/Letterhead.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00030", "DB/HeadersFooters/Src/Letterhead-with-Watermark.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] + [InlineData( + "DB009-00010", + "DB/HeadersFooters/Src/Content-Controls.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] + [InlineData( + "DB009-00020", + "DB/HeadersFooters/Src/Letterhead.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] + [InlineData( + "DB009-00030", + "DB/HeadersFooters/Src/Letterhead-with-Watermark.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] [InlineData("DB009-00040", "DB/HeadersFooters/Src/Logo.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00050", "DB/HeadersFooters/Src/Watermark-1.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00060", "DB/HeadersFooters/Src/Watermark-2.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00070", "DB/HeadersFooters/Src/Disclaimer.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] + [InlineData( + "DB009-00050", + "DB/HeadersFooters/Src/Watermark-1.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] + [InlineData( + "DB009-00060", + "DB/HeadersFooters/Src/Watermark-2.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] + [InlineData( + "DB009-00070", + "DB/HeadersFooters/Src/Disclaimer.docx", + "DB/HeadersFooters/Dest/Fax.docx", + "Templafy" + )] [InlineData("DB009-00080", "DB/HeadersFooters/Src/Footer.docx", "DB/HeadersFooters/Dest/Fax.docx", "Templafy")] - [InlineData("DB009-00110", "DB/HeadersFooters/Src/Content-Controls.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00120", "DB/HeadersFooters/Src/Letterhead.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00130", "DB/HeadersFooters/Src/Letterhead-with-Watermark.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] + [InlineData( + "DB009-00110", + "DB/HeadersFooters/Src/Content-Controls.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] + [InlineData( + "DB009-00120", + "DB/HeadersFooters/Src/Letterhead.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] + [InlineData( + "DB009-00130", + "DB/HeadersFooters/Src/Letterhead-with-Watermark.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] [InlineData("DB009-00140", "DB/HeadersFooters/Src/Logo.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00150", "DB/HeadersFooters/Src/Watermark-1.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00160", "DB/HeadersFooters/Src/Watermark-2.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00170", "DB/HeadersFooters/Src/Disclaimer.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - [InlineData("DB009-00180", "DB/HeadersFooters/Src/Footer.docx", "DB/HeadersFooters/Dest/Letter.docx", "Templafy")] - + [InlineData( + "DB009-00150", + "DB/HeadersFooters/Src/Watermark-1.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] + [InlineData( + "DB009-00160", + "DB/HeadersFooters/Src/Watermark-2.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] + [InlineData( + "DB009-00170", + "DB/HeadersFooters/Src/Disclaimer.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] + [InlineData( + "DB009-00180", + "DB/HeadersFooters/Src/Footer.docx", + "DB/HeadersFooters/Dest/Letter.docx", + "Templafy" + )] public void DB009_ImportIntoHeadersFooters(string testId, string src, string dest, string insertId) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -304,11 +382,7 @@ public void DB009_ImportIntoHeadersFooters(string testId, string src, string des } } - var sources = new List - { - new Source(wmlDestDocument), - new Source(wmlSourceDocument, insertId), - }; + var sources = new List { new Source(wmlDestDocument), new Source(wmlSourceDocument, insertId) }; var outFi = new FileInfo(Path.Combine(tempDirFullName, "Output.docx")); DocumentBuilder.BuildDocument(sources, outFi.FullName); @@ -463,33 +537,33 @@ public void DB009_ShredDocument() using (var doc = WordprocessingDocument.Open(spec.FullName, false)) { var sectionCounts = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Rollup(0, (pi, last) => (string)pi - .Elements(W.pPr) - .Elements(W.pStyle) - .Attributes(W.val) - .FirstOrDefault() == "Heading1" ? last + 1 : last); + .Rollup( + 0, + (pi, last) => + (string)pi.Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault() + == "Heading1" + ? last + 1 + : last + ); var beforeZipped = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Select((p, i) => new - { - Paragraph = p, - Index = i, - }); - var zipped = PtExtensions.PtZip(beforeZipped, sectionCounts, (pi, sc) => new - { - Paragraph = pi.Paragraph, - Index = pi.Index, - SectionIndex = sc, - }); + .Select((p, i) => new { Paragraph = p, Index = i }); + var zipped = PtExtensions.PtZip( + beforeZipped, + sectionCounts, + (pi, sc) => + new + { + Paragraph = pi.Paragraph, + Index = pi.Index, + SectionIndex = sc, + } + ); documentList = zipped .GroupAdjacent(p => p.SectionIndex) .Select(g => new DocumentInfo @@ -504,8 +578,9 @@ public void DB009_ShredDocument() { var fileName = $"DB009-Section{doc.DocumentNumber:000}.docx"; var fiSection = new FileInfo(Path.Combine(TempDir, fileName)); - var documentSource = new List { - new Source(new WmlDocument(spec.FullName), doc.Start, doc.Count, true) + var documentSource = new List + { + new Source(new WmlDocument(spec.FullName), doc.Start, doc.Count, true), }; DocumentBuilder.BuildDocument(documentSource, fiSection.FullName); Validate(fiSection); @@ -521,13 +596,11 @@ public void DB009_ShredDocument() DocumentBuilder.BuildDocument(sources, fiReassembled.FullName); using (var doc = WordprocessingDocument.Open(fiReassembled.FullName, true)) { - ReferenceAdder.AddToc(doc, "/w:document/w:body/w:p[1]", - @"TOC \o '1-3' \h \z \u", null, null); + ReferenceAdder.AddToc(doc, "/w:document/w:body/w:p[1]", @"TOC \o '1-3' \h \z \u", null, null); } Validate(fiReassembled); } - [Fact] public void DB010_InsertUsingInsertId() { @@ -544,18 +617,12 @@ public void DB010_InsertUsingInsertId() { var xDoc = doc.MainDocumentPart.GetXDocument(); var frontMatterPara = xDoc.Root.Descendants(W.txbxContent).Elements(W.p).FirstOrDefault(); - frontMatterPara.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Front"))); + frontMatterPara.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Front"))); var tbl = xDoc.Root.Element(W.body).Elements(W.tbl).FirstOrDefault(); var firstCell = tbl.Descendants(W.tr).First().Descendants(W.p).First(); - firstCell.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Liz"))); + firstCell.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Liz"))); var secondCell = tbl.Descendants(W.tr).Skip(1).First().Descendants(W.p).First(); - secondCell.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Eric"))); + secondCell.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Eric"))); doc.MainDocumentPart.PutXDocument(); } doc1.DocumentByteArray = mem.ToArray(); @@ -586,15 +653,13 @@ public void DB011_BodyAndHeaderWithShapes() new Source(new WmlDocument(source1.FullName)), new Source(new WmlDocument(source2.FullName)), }; - var processedDestDocx = - new FileInfo(Path.Combine(TempDir, "DB011-Body-And-Header-With-Shapes.docx")); + var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB011-Body-And-Header-With-Shapes.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); Validate(processedDestDocx); ValidateUniqueDocPrIds(processedDestDocx); } - [Fact] public void DB012_NumberingsWithSameAbstractNumbering() { @@ -602,12 +667,10 @@ public void DB012_NumberingsWithSameAbstractNumbering() var name = "DB012-Lists-With-Different-Numberings.docx"; var sourceDocx = new FileInfo(Path.Combine(_sourceDir.FullName, name)); - var sources = new List - { - new Source(new WmlDocument(sourceDocx.FullName)), - }; - var processedDestDocx = new FileInfo(Path.Combine(TempDir, - sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx"))); + var sources = new List { new Source(new WmlDocument(sourceDocx.FullName)) }; + var processedDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx")) + ); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); using var wDoc = WordprocessingDocument.Open(processedDestDocx.FullName, false); @@ -620,18 +683,15 @@ public void DB013a_LocalizedStyleIds_Heading() { // Each of these documents have changed the font color of the Heading 1 style, one to red, the other to green. // One of the documents were created with English as the Word display language, the other with Danish as the language. - var source1 = - new FileInfo(Path.Combine(_sourceDir.FullName, "DB013a-Red-Heading1-English.docx")); - var source2 = new FileInfo(Path.Combine(_sourceDir.FullName, - "DB013a-Green-Heading1-Danish.docx")); + var source1 = new FileInfo(Path.Combine(_sourceDir.FullName, "DB013a-Red-Heading1-English.docx")); + var source2 = new FileInfo(Path.Combine(_sourceDir.FullName, "DB013a-Green-Heading1-Danish.docx")); var sources = new List { new Source(new WmlDocument(source1.FullName)), new Source(new WmlDocument(source2.FullName)), }; - var processedDestDocx = - new FileInfo(Path.Combine(TempDir, "DB013a-Colored-Heading1.docx")); + var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB013a-Colored-Heading1.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); using var wDoc = WordprocessingDocument.Open(processedDestDocx.FullName, false); @@ -639,9 +699,9 @@ public void DB013a_LocalizedStyleIds_Heading() Assert.Equal(1, styles.Count(s => s.Element(W.name).Attribute(W.val).Value == "heading 1")); var styleIds = new HashSet(styles.Select(s => s.Attribute(W.styleId).Value)); - var paragraphStylesIds = new HashSet(wDoc.MainDocumentPart.GetXDocument() - .Descendants(W.pStyle) - .Select(p => p.Attribute(W.val).Value)); + var paragraphStylesIds = new HashSet( + wDoc.MainDocumentPart.GetXDocument().Descendants(W.pStyle).Select(p => p.Attribute(W.val).Value) + ); Assert.Subset(styleIds, paragraphStylesIds); } @@ -650,18 +710,15 @@ public void DB013b_LocalizedStyleIds_List() { // Each of these documents have changed the font color of the List Paragraph style, one to orange, the other to blue. // One of the documents were created with English as the Word display language, the other with Danish as the language. - var source1 = - new FileInfo(Path.Combine(_sourceDir.FullName, "DB013b-Orange-List-Danish.docx")); - var source2 = new FileInfo(Path.Combine(_sourceDir.FullName, - "DB013b-Blue-List-English.docx")); + var source1 = new FileInfo(Path.Combine(_sourceDir.FullName, "DB013b-Orange-List-Danish.docx")); + var source2 = new FileInfo(Path.Combine(_sourceDir.FullName, "DB013b-Blue-List-English.docx")); var sources = new List { new Source(new WmlDocument(source1.FullName)), new Source(new WmlDocument(source2.FullName)), }; - var processedDestDocx = - new FileInfo(Path.Combine(TempDir, "DB013b-Colored-List.docx")); + var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB013b-Colored-List.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); using var wDoc = WordprocessingDocument.Open(processedDestDocx.FullName, false); @@ -669,9 +726,9 @@ public void DB013b_LocalizedStyleIds_List() Assert.Equal(1, styles.Count(s => s.Element(W.name).Attribute(W.val).Value == "List Paragraph")); var styleIds = new HashSet(styles.Select(s => s.Attribute(W.styleId).Value)); - var paragraphStylesIds = new HashSet(wDoc.MainDocumentPart.GetXDocument() - .Descendants(W.pStyle) - .Select(p => p.Attribute(W.val).Value)); + var paragraphStylesIds = new HashSet( + wDoc.MainDocumentPart.GetXDocument().Descendants(W.pStyle).Select(p => p.Attribute(W.val).Value) + ); Assert.Subset(styleIds, paragraphStylesIds); } @@ -680,10 +737,7 @@ public void DB014_KeepWebExtensions() { var source = new FileInfo(Path.Combine(_sourceDir.FullName, "DB014-WebExtensions.docx")); - var sources = new List - { - new Source(new WmlDocument(source.FullName)), - }; + var sources = new List { new Source(new WmlDocument(source.FullName)) }; var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB014-WebExtensions.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); Validate(processedDestDocx); @@ -699,10 +753,7 @@ public void DB015_LatentStyles() { var source = new FileInfo(Path.Combine(_sourceDir.FullName, "DB015-LatentStyles.docx")); - var sources = new List - { - new Source(new WmlDocument(source.FullName)), - }; + var sources = new List { new Source(new WmlDocument(source.FullName)) }; var processedDestDocx = new FileInfo(Path.Combine(TempDir, "DB015-LatentStyles.docx")); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); Validate(processedDestDocx); @@ -721,63 +772,181 @@ public void DB0016_DocDefaultStyles() var name = "DB0016-DocDefaultStyles.docx"; var sourceDocx = new FileInfo(Path.Combine(_sourceDir.FullName, name)); - var sources = new List - { - new Source(new WmlDocument(sourceDocx.FullName), true), - }; - var processedDestDocx = new FileInfo(Path.Combine(TempDir, - sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx"))); + var sources = new List { new Source(new WmlDocument(sourceDocx.FullName), true) }; + var processedDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-DocumentBuilder.docx")) + ); DocumentBuilder.BuildDocument(sources, processedDestDocx.FullName); using var wDoc = WordprocessingDocument.Open(processedDestDocx.FullName, true); - var styles = wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument().Root.Elements(W.docDefaults).ToArray(); + var styles = wDoc + .MainDocumentPart.StyleDefinitionsPart.GetXDocument() + .Root.Elements(W.docDefaults) + .ToArray(); Assert.Single(styles); } [Theory] - [InlineData("DB100-00010", "DB/GlossaryDocuments/CellLevelContentControl-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/CellLevelContentControl.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00020", "DB/GlossaryDocuments/InlineContentControl-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/InlineContentControl.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00030", "DB/GlossaryDocuments/MultilineWithBulletPoints-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/MultilineWithBulletPoints.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00040", "DB/GlossaryDocuments/NestedContentControl-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/NestedContentControl.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00050", "DB/GlossaryDocuments/RowLevelContentControl-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/RowLevelContentControl.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00060", "DB/GlossaryDocuments/ContentControlDanishProofingLanguage-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/ContentControlDanishProofingLanguage.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00070", "DB/GlossaryDocuments/ContentControlEnglishProofingLanguage-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/ContentControlEnglishProofingLanguage.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00080", "DB/GlossaryDocuments/ContentControlMixedProofingLanguage-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/ContentControlMixedProofingLanguage.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00090", "DB/GlossaryDocuments/ContentControlWithContent-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/ContentControlWithContent.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00100", "DB/GlossaryDocuments/FooterContent-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/FooterContent.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00110", "DB/GlossaryDocuments/HeaderContent-built.docx", "DB/GlossaryDocuments/BaseDocument.docx,0,4", "DB/GlossaryDocuments/HeaderContent.docx", "DB/GlossaryDocuments/BaseDocument.docx,4", null, null, null)] - [InlineData("DB100-00200", null, "DB/GlossaryDocuments/BaseDocument.docx", "DB/GlossaryDocuments/CellLevelContentControl.docx", "DB/GlossaryDocuments/NestedContentControl.docx", null, null, null)] - - public void WithGlossaryDocuments(string testId, string baseline, string src1, string src2, string src3, string src4, string src5, string src6) + [InlineData( + "DB100-00010", + "DB/GlossaryDocuments/CellLevelContentControl-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/CellLevelContentControl.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00020", + "DB/GlossaryDocuments/InlineContentControl-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/InlineContentControl.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00030", + "DB/GlossaryDocuments/MultilineWithBulletPoints-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/MultilineWithBulletPoints.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00040", + "DB/GlossaryDocuments/NestedContentControl-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/NestedContentControl.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00050", + "DB/GlossaryDocuments/RowLevelContentControl-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/RowLevelContentControl.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00060", + "DB/GlossaryDocuments/ContentControlDanishProofingLanguage-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/ContentControlDanishProofingLanguage.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00070", + "DB/GlossaryDocuments/ContentControlEnglishProofingLanguage-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/ContentControlEnglishProofingLanguage.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00080", + "DB/GlossaryDocuments/ContentControlMixedProofingLanguage-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/ContentControlMixedProofingLanguage.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00090", + "DB/GlossaryDocuments/ContentControlWithContent-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/ContentControlWithContent.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00100", + "DB/GlossaryDocuments/FooterContent-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/FooterContent.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00110", + "DB/GlossaryDocuments/HeaderContent-built.docx", + "DB/GlossaryDocuments/BaseDocument.docx,0,4", + "DB/GlossaryDocuments/HeaderContent.docx", + "DB/GlossaryDocuments/BaseDocument.docx,4", + null, + null, + null + )] + [InlineData( + "DB100-00200", + null, + "DB/GlossaryDocuments/BaseDocument.docx", + "DB/GlossaryDocuments/CellLevelContentControl.docx", + "DB/GlossaryDocuments/NestedContentControl.docx", + null, + null, + null + )] + public void WithGlossaryDocuments( + string testId, + string baseline, + string src1, + string src2, + string src3, + string src4, + string src5, + string src6 + ) { - var rawSources = new[] { src1, src2, src3, src4, src5, src6, }; + var rawSources = new[] { src1, src2, src3, src4, src5, src6 }; var sourcesStr = rawSources.Where(s => s != null).ToArray(); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Load the source documents - var sources = sourcesStr.Select(s => - { - var spl = s.Split(','); - if (spl.Length == 1) - { - var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, s)); - var wmlSource = new WmlDocument(sourceFi.FullName); - return new Source(wmlSource); - } - else if (spl.Length == 2) + var sources = sourcesStr + .Select(s => { - var start = int.Parse(spl[1]); - var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, spl[0])); - return new Source(sourceFi.FullName, start, true); - } - else - { - var start = int.Parse(spl[1]); - var count = int.Parse(spl[2]); - var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, spl[0])); - return new Source(sourceFi.FullName, start, count, true); - } - }) + var spl = s.Split(','); + if (spl.Length == 1) + { + var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, s)); + var wmlSource = new WmlDocument(sourceFi.FullName); + return new Source(wmlSource); + } + else if (spl.Length == 2) + { + var start = int.Parse(spl[1]); + var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, spl[0])); + return new Source(sourceFi.FullName, start, true); + } + else + { + var start = int.Parse(spl[1]); + var count = int.Parse(spl[2]); + var sourceFi = new FileInfo(Path.Combine(_sourceDir.FullName, spl[0])); + return new Source(sourceFi.FullName, start, count, true); + } + }) .Cast() .ToList(); @@ -822,37 +991,38 @@ private void Validate(FileInfo fi) using var wDoc = WordprocessingDocument.Open(fi.FullName, false); Validate(wDoc, s_expectedErrors); } - - private static readonly List s_expectedErrors = new() - { - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenVBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowFirstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowLastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowFirstColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowLastColumn' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noVBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddHBand' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddVBand' attribute is not declared.", - "The element has unexpected child element 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:updateFields'.", - "The attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:name' has invalid value 'useWord2013TrackBottomHyphenation'. The Enumeration constraint failed.", - "The 'http://schemas.microsoft.com/office/word/2012/wordml:restartNumberingAfterBreak' attribute is not declared.", - "Attribute 'id' should have unique value. Its current value '", - "The 'urn:schemas-microsoft-com:mac:vml:blur' attribute is not declared.", - "Attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:id' should have unique value. Its current value '", - "The element has unexpected child element 'http://schemas.microsoft.com/office/word/2012/wordml:", - "The element has invalid child element 'http://schemas.microsoft.com/office/word/2012/wordml:", - "The 'urn:schemas-microsoft-com:mac:vml:complextextbox' attribute is not declared.", - "http://schemas.microsoft.com/office/word/2010/wordml:", - "http://schemas.microsoft.com/office/word/2008/9/12/wordml:", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:allStyles' attribute is not declared.", - "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:customStyles' attribute is not declared.", - }; + + private static readonly List s_expectedErrors = + new() + { + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:evenVBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowFirstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRowLastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowFirstColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRowLastColumn' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:noVBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddHBand' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:oddVBand' attribute is not declared.", + "The element has unexpected child element 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:updateFields'.", + "The attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:name' has invalid value 'useWord2013TrackBottomHyphenation'. The Enumeration constraint failed.", + "The 'http://schemas.microsoft.com/office/word/2012/wordml:restartNumberingAfterBreak' attribute is not declared.", + "Attribute 'id' should have unique value. Its current value '", + "The 'urn:schemas-microsoft-com:mac:vml:blur' attribute is not declared.", + "Attribute 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:id' should have unique value. Its current value '", + "The element has unexpected child element 'http://schemas.microsoft.com/office/word/2012/wordml:", + "The element has invalid child element 'http://schemas.microsoft.com/office/word/2012/wordml:", + "The 'urn:schemas-microsoft-com:mac:vml:complextextbox' attribute is not declared.", + "http://schemas.microsoft.com/office/word/2010/wordml:", + "http://schemas.microsoft.com/office/word/2008/9/12/wordml:", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:allStyles' attribute is not declared.", + "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:customStyles' attribute is not declared.", + }; } } #endif diff --git a/Clippit.Tests/Word/HtmlConverterTests.cs b/Clippit.Tests/Word/HtmlConverterTests.cs index 3c79e21b..47c879ba 100644 --- a/Clippit.Tests/Word/HtmlConverterTests.cs +++ b/Clippit.Tests/Word/HtmlConverterTests.cs @@ -13,7 +13,6 @@ using DocumentFormat.OpenXml.Packaging; using Xunit; using Xunit.Abstractions; - #if DO_CONVERSION_VIA_WORD using Word = Microsoft.Office.Interop.Word; #endif @@ -24,10 +23,9 @@ namespace Clippit.Tests.Word { public class HtmlConverterTests : TestsBase { - public HtmlConverterTests(ITestOutputHelper log) : base(log) - { - } - + public HtmlConverterTests(ITestOutputHelper log) + : base(log) { } + public static bool s_CopySourceFiles = true; public static bool s_CopyFormattingAssembledDocx = true; public static bool s_ConvertUsingWord = true; @@ -89,30 +87,36 @@ public HtmlConverterTests(ITestOutputHelper log) : base(log) [InlineData("HC051-Shaded-Text-02.docx")] [InlineData("HC060-Image-with-Hyperlink.docx")] [InlineData("HC061-Hyperlink-in-Field.docx")] - public void HC001(string name) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); #if COPY_FILES_FOR_DEBUGGING - var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-1-Source.docx"))); + var sourceCopiedToDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-1-Source.docx")) + ); if (!sourceCopiedToDestDocx.Exists) File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); - var assembledFormattingDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-2-FormattingAssembled.docx"))); + var assembledFormattingDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-2-FormattingAssembled.docx")) + ); if (!assembledFormattingDestDocx.Exists) CopyFormattingAssembledDocx(sourceDocx, assembledFormattingDestDocx); #endif - var oxPtConvertedDestHtml = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-3-OxPt.html"))); + var oxPtConvertedDestHtml = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-3-OxPt.html")) + ); ConvertToHtml(sourceDocx, oxPtConvertedDestHtml); #if DO_CONVERSION_VIA_WORD - var wordConvertedDocHtml = new FileInfo(Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", "-4-Word.html"))); + var wordConvertedDocHtml = new FileInfo( + Path.Combine(TestUtil.TempDir.FullName, sourceDocx.Name.Replace(".docx", "-4-Word.html")) + ); ConvertToHtmlUsingWord(sourceDocx, wordConvertedDocHtml); #endif - } [Theory] @@ -122,7 +126,9 @@ public void HC002_NoCssClasses(string name) var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var oxPtConvertedDestHtml = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-5-OxPt-No-CSS-Classes.html"))); + var oxPtConvertedDestHtml = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-5-OxPt-No-CSS-Classes.html")) + ); ConvertToHtmlNoCssClasses(sourceDocx, oxPtConvertedDestHtml); } @@ -133,7 +139,6 @@ private static void CopyFormattingAssembledDocx(FileInfo source, FileInfo dest) ms.Write(ba, 0, ba.Length); using (var wordDoc = WordprocessingDocument.Open(ms, true)) { - RevisionAccepter.AcceptRevisions(wordDoc); var simplifyMarkupSettings = new SimplifyMarkupSettings { @@ -160,11 +165,10 @@ private static void CopyFormattingAssembledDocx(FileInfo source, FileInfo dest) RestrictToSupportedNumberingFormats = false, CreateHtmlConverterAnnotationAttributes = true, OrderElementsPerStandard = false, - ListItemRetrieverSettings = - new ListItemRetrieverSettings() - { - ListItemTextImplementations = ListItemRetrieverSettings.DefaultListItemTextImplementations, - }, + ListItemRetrieverSettings = new ListItemRetrieverSettings() + { + ListItemTextImplementations = ListItemRetrieverSettings.DefaultListItemTextImplementations, + }, }; FormattingAssembler.AssembleFormatting(wordDoc, formattingAssemblerSettings); @@ -198,7 +202,7 @@ private static void ConvertToHtml(FileInfo sourceDocx, FileInfo destFileName) { ++imageCounter; return ImageHelper.DefaultImageHandler(imageInfo, imageDirectoryName, imageCounter); - } + }, }; var html = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); @@ -238,7 +242,7 @@ private static void ConvertToHtmlNoCssClasses(FileInfo sourceDocx, FileInfo dest { ++imageCounter; return ImageHelper.DefaultImageHandler(imageInfo, imageDirectoryName, imageCounter); - } + }, }; var html = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); @@ -274,7 +278,6 @@ public static void ConvertToHtmlUsingWord(FileInfo sourceFileName, FileInfo dest } #endif } - } #endif diff --git a/Clippit.Tests/Word/MarkupSimplifierTests.cs b/Clippit.Tests/Word/MarkupSimplifierTests.cs index 133326c0..4f72c9dc 100644 --- a/Clippit.Tests/Word/MarkupSimplifierTests.cs +++ b/Clippit.Tests/Word/MarkupSimplifierTests.cs @@ -19,7 +19,7 @@ public class MarkupSimplifierTests private const string SmartTagDocumentTextValue = "The countries include Algeria, Botswana, and Sri Lanka."; private const string SmartTagDocumentXmlString = -@" + @" @@ -57,7 +57,7 @@ public class MarkupSimplifierTests "; private const string SdtDocumentXmlString = -@" + @" @@ -75,7 +75,7 @@ public class MarkupSimplifierTests "; private const string GoBackBookmarkDocumentXmlString = -@" + @" @@ -120,10 +120,7 @@ public void CanRemoveContentControls() MarkupSimplifier.SimplifyMarkup(wordDocument, settings); partDocument = part.GetXDocument(); - var element = partDocument - .Descendants(W.body) - .Descendants() - .First(); + var element = partDocument.Descendants(W.body).Descendants().First(); Assert.False(partDocument.Descendants(W.sdt).Any()); Assert.Equal(W.p, element.Name); @@ -133,12 +130,11 @@ public void CanRemoveContentControls() public void CanRemoveGoBackBookmarks() { var partDocument = XDocument.Parse(GoBackBookmarkDocumentXmlString); - Assert.Contains(partDocument - .Descendants(W.bookmarkStart) -, e => e.Attribute(W.name).Value == "_GoBack" && e.Attribute(W.id).Value == "0"); - Assert.Contains(partDocument - .Descendants(W.bookmarkEnd) -, e => e.Attribute(W.id).Value == "0"); + Assert.Contains( + partDocument.Descendants(W.bookmarkStart), + e => e.Attribute(W.name).Value == "_GoBack" && e.Attribute(W.id).Value == "0" + ); + Assert.Contains(partDocument.Descendants(W.bookmarkEnd), e => e.Attribute(W.id).Value == "0"); using var stream = new MemoryStream(); using var wordDocument = WordprocessingDocument.Create(stream, DocumentType); diff --git a/Clippit.Tests/Word/PowerToolsBlockExtensionsTests.cs b/Clippit.Tests/Word/PowerToolsBlockExtensionsTests.cs index 81964506..11a7cf1a 100644 --- a/Clippit.Tests/Word/PowerToolsBlockExtensionsTests.cs +++ b/Clippit.Tests/Word/PowerToolsBlockExtensionsTests.cs @@ -54,7 +54,7 @@ public void MustBeginPowerToolsBlockToUsePowerTools() // Get content through the PowerTools in the exact same way as above, // noting that we have not used the BeginPowerToolsBlock method to // mark the beginning of the next PowerTools Block. - // What we will see in this case is that we still only get the first + // What we will see in this case is that we still only get the first // paragraph. This is caused by the GetXDocument method using the cached // XDocument, i.e., the annotation, rather reading the part's stream again. content = part.GetXDocument(); @@ -91,7 +91,7 @@ public void MustEndPowerToolsBlockToUseStronglyTypedClasses() body.AppendChild(new Paragraph(new Run(new Text("Added through SDK")))); // Begin the PowerTools Block, which saves any changes made through the strongly - // typed SDK classes to the parts of the WordprocessingDocument. + // typed SDK classes to the parts of the WordprocessingDocument. // In this case, this could also be done by invoking the Save method on the // WordprocessingDocument, which will save all parts that had changes, or by // invoking part.RootElement.Save() for the one part that was changed. @@ -123,7 +123,6 @@ public void MustEndPowerToolsBlockToUseStronglyTypedClasses() Assert.Equal("Added through SDK", paragraphs[0].InnerText); Assert.Equal("Added through PowerTools", paragraphs[1].InnerText); } - } } diff --git a/Clippit.Tests/Word/PowerToolsBlockTests.cs b/Clippit.Tests/Word/PowerToolsBlockTests.cs index 17aca070..23558243 100644 --- a/Clippit.Tests/Word/PowerToolsBlockTests.cs +++ b/Clippit.Tests/Word/PowerToolsBlockTests.cs @@ -17,10 +17,9 @@ namespace Clippit.Tests.Word { public class PowerToolsBlockTests : TestsBase { - public PowerToolsBlockTests(ITestOutputHelper log) : base(log) - { - } - + public PowerToolsBlockTests(ITestOutputHelper log) + : base(log) { } + [Fact] public void CanUsePowerToolsBlockToDemarcateApis() { diff --git a/Clippit.Tests/Word/RevisionAccepterTests.cs b/Clippit.Tests/Word/RevisionAccepterTests.cs index 22504cfa..3cbe5ed3 100644 --- a/Clippit.Tests/Word/RevisionAccepterTests.cs +++ b/Clippit.Tests/Word/RevisionAccepterTests.cs @@ -12,10 +12,9 @@ namespace Clippit.Tests.Word { public class RevisionAccepterTests : TestsBase { - public RevisionAccepterTests(ITestOutputHelper log) : base(log) - { - } - + public RevisionAccepterTests(ITestOutputHelper log) + : base(log) { } + [Theory] [InlineData("RA001-Tracked-Revisions-01.docx")] [InlineData("RA001-Tracked-Revisions-02.docx")] @@ -26,7 +25,9 @@ public void RA001(string name) var notAccepted = new WmlDocument(sourceDocx.FullName); var afterAccepting = RevisionAccepter.AcceptRevisions(notAccepted); - var processedDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-RevisionAccepter.docx"))); + var processedDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-processed-by-RevisionAccepter.docx")) + ); afterAccepting.SaveAs(processedDestDocx.FullName); } } diff --git a/Clippit.Tests/Word/RevisionProcessorTests.cs b/Clippit.Tests/Word/RevisionProcessorTests.cs index 2491be52..836e500a 100644 --- a/Clippit.Tests/Word/RevisionProcessorTests.cs +++ b/Clippit.Tests/Word/RevisionProcessorTests.cs @@ -14,14 +14,14 @@ namespace Clippit.Tests.Word { public class RevisionProcessorTests : TestsBase { - public RevisionProcessorTests(ITestOutputHelper log) : base(log) - { - } - + public RevisionProcessorTests(ITestOutputHelper log) + : base(log) { } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // perf settings public static bool m_CopySourceFilesToTempDir = true; public static bool m_OpenTempDirInExplorer = false; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Theory] @@ -81,17 +81,25 @@ public void RP001(string name) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceFi = new FileInfo(Path.Combine(sourceDir.FullName, name)); - var baselineAcceptedFi = new FileInfo(Path.Combine(sourceDir.FullName, name.Replace(".docx", "-Accepted.docx"))); - var baselineRejectedFi = new FileInfo(Path.Combine(sourceDir.FullName, name.Replace(".docx", "-Rejected.docx"))); + var baselineAcceptedFi = new FileInfo( + Path.Combine(sourceDir.FullName, name.Replace(".docx", "-Accepted.docx")) + ); + var baselineRejectedFi = new FileInfo( + Path.Combine(sourceDir.FullName, name.Replace(".docx", "-Rejected.docx")) + ); var sourceWml = new WmlDocument(sourceFi.FullName); var afterRejectingWml = RevisionProcessor.RejectRevisions(sourceWml); var afterAcceptingWml = RevisionProcessor.AcceptRevisions(sourceWml); - var processedAcceptedFi = new FileInfo(Path.Combine(TempDir, sourceFi.Name.Replace(".docx", "-Accepted.docx"))); + var processedAcceptedFi = new FileInfo( + Path.Combine(TempDir, sourceFi.Name.Replace(".docx", "-Accepted.docx")) + ); afterAcceptingWml.SaveAs(processedAcceptedFi.FullName); - var processedRejectedFi = new FileInfo(Path.Combine(TempDir, sourceFi.Name.Replace(".docx", "-Rejected.docx"))); + var processedRejectedFi = new FileInfo( + Path.Combine(TempDir, sourceFi.Name.Replace(".docx", "-Rejected.docx")) + ); afterRejectingWml.SaveAs(processedRejectedFi.FullName); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -126,8 +134,18 @@ public void RP001(string name) var batchFileName = "Copy-Gen-Files-To-TestFiles.bat"; var batchFi = new FileInfo(Path.Combine(TempDir, batchFileName)); var batch = ""; - batch += "copy " + processedAcceptedFi.FullName + " " + baselineAcceptedFi.FullName + Environment.NewLine; - batch += "copy " + processedRejectedFi.FullName + " " + baselineRejectedFi.FullName + Environment.NewLine; + batch += + "copy " + + processedAcceptedFi.FullName + + " " + + baselineAcceptedFi.FullName + + Environment.NewLine; + batch += + "copy " + + processedRejectedFi.FullName + + " " + + baselineRejectedFi.FullName + + Environment.NewLine; if (batchFi.Exists) File.AppendAllText(batchFi.FullName, batch); else @@ -202,7 +220,6 @@ public void RP001(string name) Assert.Fail("No Rejected baseline document"); } } - } } diff --git a/Clippit.Tests/Word/Samples/DocumentAssemblerSamples.cs b/Clippit.Tests/Word/Samples/DocumentAssemblerSamples.cs index 765287b3..eb5945b8 100644 --- a/Clippit.Tests/Word/Samples/DocumentAssemblerSamples.cs +++ b/Clippit.Tests/Word/Samples/DocumentAssemblerSamples.cs @@ -9,20 +9,19 @@ namespace Clippit.Tests.Word.Samples { public class DocumentAssemblerSamples : TestsBase { - public DocumentAssemblerSamples(ITestOutputHelper log) : base(log) - { - } + public DocumentAssemblerSamples(ITestOutputHelper log) + : base(log) { } private const string FolderPath = "../../../Word/Samples/DocumentAssembler/"; private const string TemplateDocumentFilePath = FolderPath + "TemplateDocument.docx"; private const string TemplateDataFilePath = FolderPath + "Data.xml"; - + [Fact] public void Sample1() { var wmlDoc = new WmlDocument(TemplateDocumentFilePath); var data = XElement.Load(TemplateDataFilePath); - + var wmlAssembledDoc = DocumentAssembler.AssembleDocument(wmlDoc, data, out var templateError); Assert.False(templateError, "Errors in template"); @@ -31,7 +30,7 @@ public void Sample1() assembledDoc.Delete(); wmlAssembledDoc.SaveAs(assembledDoc.FullName); } - + [Fact] public void Sample2() { @@ -55,9 +54,9 @@ public void Sample2() wmlAssembledDoc.SaveAs(assembledDoc.FullName); } } - - - private static readonly string[] s_productNames = { + + private static readonly string[] s_productNames = + { "Unicycle", "Bicycle", "Tricycle", @@ -73,20 +72,24 @@ private static XElement GenerateDataFromDataSource(FileInfo dataFi) var r = new Random(); for (var i = 0; i < numberOfDocumentsToGenerate; ++i) { - var customer = new XElement("Customer", + var customer = new XElement( + "Customer", new XElement("CustomerID", i + 1), new XElement("Name", "Eric White"), new XElement("HighValueCustomer", r.Next(2) == 0 ? "True" : "False"), - new XElement("Orders")); + new XElement("Orders") + ); var orders = customer.Element("Orders"); var numberOfOrders = r.Next(10) + 1; for (var j = 0; j < numberOfOrders; j++) { - var order = new XElement("Order", + var order = new XElement( + "Order", new XAttribute("Number", j + 1), new XElement("ProductDescription", s_productNames[r.Next(s_productNames.Length)]), new XElement("Quantity", r.Next(10)), - new XElement("OrderDate", "September 26, 2015")); + new XElement("OrderDate", "September 26, 2015") + ); orders.Add(order); } customers.Add(customer); diff --git a/Clippit.Tests/Word/Samples/DocumentBuilderSamples.cs b/Clippit.Tests/Word/Samples/DocumentBuilderSamples.cs index f930522f..9a2ef9eb 100644 --- a/Clippit.Tests/Word/Samples/DocumentBuilderSamples.cs +++ b/Clippit.Tests/Word/Samples/DocumentBuilderSamples.cs @@ -12,12 +12,10 @@ namespace Clippit.Tests.Word.Samples { public class DocumentBuilderSamples : TestsBase { - public DocumentBuilderSamples(ITestOutputHelper log) : base(log) - { - } + public DocumentBuilderSamples(ITestOutputHelper log) + : base(log) { } - private static string GetFilePath(string path) => - Path.Combine("../../../Word/Samples/DocumentBuilder/", path); + private static string GetFilePath(string path) => Path.Combine("../../../Word/Samples/DocumentBuilder/", path); [Fact] public void Sample1() @@ -27,10 +25,7 @@ public void Sample1() var source3 = GetFilePath("Sample1/Source3.docx"); // Create new document from 10 paragraphs starting at paragraph 5 of Source1.docx - var sources = new List - { - new Source(new WmlDocument(source1), 5, 10, true), - }; + var sources = new List { new Source(new WmlDocument(source1), 5, 10, true) }; DocumentBuilder.BuildDocument(sources, Path.Combine(TempDir, "Out1.docx")); // Create new document from paragraph 1, and paragraphs 5 through end of Source3.docx. @@ -69,8 +64,8 @@ public void Sample1() new Source(new WmlDocument(source2), 0, 5, true), }; var out5 = DocumentBuilder.BuildDocument(sources); - out5.SaveAs(Path.Combine(TempDir, "Out5.docx")); // save it to the file system, but we could just as easily done something - // else with it. + out5.SaveAs(Path.Combine(TempDir, "Out5.docx")); // save it to the file system, but we could just as easily done something + // else with it. } private class DocumentInfo @@ -97,21 +92,21 @@ public void Sample2() using (var doc = WordprocessingDocument.Open(GetFilePath("Sample2/Notes.docx"), false)) { sources = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Select((p, i) => new { Paragraph = p, Index = i, }) - .GroupAdjacent(pi => (string)pi.Paragraph - .Elements(W.pPr) - .Elements(W.pStyle) - .Attributes(W.val) - .FirstOrDefault() != "Note") + .Select((p, i) => new { Paragraph = p, Index = i }) + .GroupAdjacent(pi => + (string)pi.Paragraph.Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault() + != "Note" + ) .Where(g => g.Key) .Select(g => new Source( - new WmlDocument(GetFilePath("Sample2/Notes.docx")), g.First().Index, - g.Last().Index - g.First().Index + 1, true)) + new WmlDocument(GetFilePath("Sample2/Notes.docx")), + g.First().Index, + g.Last().Index - g.First().Index + 1, + true + )) .Cast() .ToList(); } @@ -123,27 +118,33 @@ public void Sample2() using (var doc = WordprocessingDocument.Open(GetFilePath("Sample2/Spec.docx"), false)) { var sectionCounts = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Rollup(0, (pi, last) => (string)pi - .Elements(W.pPr) - .Elements(W.pStyle) - .Attributes(W.val) - .FirstOrDefault() == "Heading1" - ? last + 1 - : last); + .Rollup( + 0, + (pi, last) => + (string)pi.Elements(W.pPr).Elements(W.pStyle).Attributes(W.val).FirstOrDefault() + == "Heading1" + ? last + 1 + : last + ); var beforeZipped = doc - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) + .MainDocumentPart.GetXDocument() + .Root.Element(W.body) .Elements() - .Select((p, i) => new { Paragraph = p, Index = i, }); - var zipped = PtExtensions.PtZip(beforeZipped, sectionCounts, - (pi, sc) => new { Paragraph = pi.Paragraph, Index = pi.Index, SectionIndex = sc, }); + .Select((p, i) => new { Paragraph = p, Index = i }); + var zipped = PtExtensions.PtZip( + beforeZipped, + sectionCounts, + (pi, sc) => + new + { + Paragraph = pi.Paragraph, + Index = pi.Index, + SectionIndex = sc, + } + ); documentList = zipped .GroupAdjacent(p => p.SectionIndex) .Select(g => new DocumentInfo @@ -160,7 +161,7 @@ public void Sample2() var fileName = $"Section{doc.DocumentNumber:000}.docx"; var documentSource = new List { - new Source(new WmlDocument(GetFilePath("Sample2/Spec.docx")), doc.Start, doc.Count, true) + new Source(new WmlDocument(GetFilePath("Sample2/Spec.docx")), doc.Start, doc.Count, true), }; DocumentBuilder.BuildDocument(documentSource, Path.Combine(TempDir, fileName)); } @@ -185,18 +186,12 @@ public void Sample3() { var xDoc = doc.MainDocumentPart.GetXDocument(); var frontMatterPara = xDoc.Root.Descendants(W.txbxContent).Elements(W.p).FirstOrDefault(); - frontMatterPara.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Front"))); + frontMatterPara.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Front"))); var tbl = xDoc.Root.Element(W.body).Elements(W.tbl).FirstOrDefault(); var firstCell = tbl.Descendants(W.tr).First().Descendants(W.p).First(); - firstCell.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Liz"))); + firstCell.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Liz"))); var secondCell = tbl.Descendants(W.tr).Skip(1).First().Descendants(W.p).First(); - secondCell.ReplaceWith( - new XElement(PtOpenXml.Insert, - new XAttribute("Id", "Eric"))); + secondCell.ReplaceWith(new XElement(PtOpenXml.Insert, new XAttribute("Id", "Eric"))); doc.MainDocumentPart.PutXDocument(); } doc1.DocumentByteArray = mem.ToArray(); @@ -204,12 +199,12 @@ public void Sample3() var outFileName = Path.Combine(TempDir, "Out.docx"); var sources = new List() - { - new Source(doc1, true), - new Source(new WmlDocument(GetFilePath("Sample3/Insert-01.docx")), "Liz"), - new Source(new WmlDocument(GetFilePath("Sample3/Insert-02.docx")), "Eric"), - new Source(new WmlDocument(GetFilePath("Sample3/FrontMatter.docx")), "Front"), - }; + { + new Source(doc1, true), + new Source(new WmlDocument(GetFilePath("Sample3/Insert-01.docx")), "Liz"), + new Source(new WmlDocument(GetFilePath("Sample3/Insert-02.docx")), "Eric"), + new Source(new WmlDocument(GetFilePath("Sample3/FrontMatter.docx")), "Front"), + }; DocumentBuilder.BuildDocument(sources, outFileName); } @@ -220,33 +215,19 @@ public void Sample4() using var streamDoc = new OpenXmlMemoryStreamDocument(solarSystemDoc); using var solarSystem = streamDoc.GetWordprocessingDocument(); // get children elements of the element - var q1 = solarSystem - .MainDocumentPart - .GetXDocument() - .Root - .Element(W.body) - .Elements(); + var q1 = solarSystem.MainDocumentPart.GetXDocument().Root.Element(W.body).Elements(); // project collection of tuples containing element and type - var q2 = q1 - .Select( - e => - { - var keyForGroupAdjacent = ".NonContentControl"; - if (e.Name == W.sdt) - keyForGroupAdjacent = e.Element(W.sdtPr) - .Element(W.tag) - .Attribute(W.val) - .Value; - if (e.Name == W.sectPr) - keyForGroupAdjacent = null; - return new - { - Element = e, - KeyForGroupAdjacent = keyForGroupAdjacent - }; - } - ).Where(e => e.KeyForGroupAdjacent != null); + var q2 = q1.Select(e => + { + var keyForGroupAdjacent = ".NonContentControl"; + if (e.Name == W.sdt) + keyForGroupAdjacent = e.Element(W.sdtPr).Element(W.tag).Attribute(W.val).Value; + if (e.Name == W.sectPr) + keyForGroupAdjacent = null; + return new { Element = e, KeyForGroupAdjacent = keyForGroupAdjacent }; + }) + .Where(e => e.KeyForGroupAdjacent != null); // group by type var q3 = q2.GroupAdjacent(e => e.KeyForGroupAdjacent); @@ -270,35 +251,29 @@ public void Sample4() } // project collection with opened WordProcessingDocument - var q4 = q3 - .Select(g => new - { - Group = g, - Document = g.Key != ".NonContentControl" ? - new WmlDocument(GetFilePath("Sample4/" + g.Key + ".docx")) : - solarSystemDoc - }); + var q4 = q3.Select(g => new + { + Group = g, + Document = g.Key != ".NonContentControl" + ? new WmlDocument(GetFilePath("Sample4/" + g.Key + ".docx")) + : solarSystemDoc, + }); // project collection of OpenXml.PowerTools.Source - var sources = q4 - .Select( - g => - { - if (g.Group.Key == ".NonContentControl") - return new Source( - g.Document, - g.Group - .First() - .Element - .ElementsBeforeSelf() - .Count(), - g.Group - .Count(), - false); - else - return new Source(g.Document, false); - } - ).Cast().ToList(); + var sources = q4.Select(g => + { + if (g.Group.Key == ".NonContentControl") + return new Source( + g.Document, + g.Group.First().Element.ElementsBeforeSelf().Count(), + g.Group.Count(), + false + ); + else + return new Source(g.Document, false); + }) + .Cast() + .ToList(); DocumentBuilder.BuildDocument(sources, Path.Combine(TempDir, "solar-system-new.docx")); } diff --git a/Clippit.Tests/Word/Samples/FieldRetrieverSamples.cs b/Clippit.Tests/Word/Samples/FieldRetrieverSamples.cs index 0b685bf9..3c9b1041 100644 --- a/Clippit.Tests/Word/Samples/FieldRetrieverSamples.cs +++ b/Clippit.Tests/Word/Samples/FieldRetrieverSamples.cs @@ -10,12 +10,10 @@ namespace Clippit.Tests.Word.Samples { public class FieldRetrieverSamples : TestsBase { - public FieldRetrieverSamples(ITestOutputHelper log) : base(log) - { - } + public FieldRetrieverSamples(ITestOutputHelper log) + : base(log) { } - private static string GetFilePath(string path) => - Path.Combine("../../../Word/Samples/FieldRetriever/", path); + private static string GetFilePath(string path) => Path.Combine("../../../Word/Samples/FieldRetriever/", path); [Fact] public void Sample1() @@ -51,31 +49,31 @@ private static void ScrubFooter(WordprocessingDocument wDoc, string[] fieldTypes private static void RemoveAllButSpecificFields(XElement root, string[] fieldTypesToRetain) { var cachedAnnotationInformation = root.Annotation>>(); - var runsToKeep = cachedAnnotationInformation.SelectMany(item => root.Descendants() - .Where(d => - { - var stack = d.Annotation>(); - return stack != null && stack.Any(stackItem => stackItem.Id == item.Key); - }) - .Select(d => d.AncestorsAndSelf(W.r).FirstOrDefault()) - .GroupAdjacent(o => o) - .Select(g => g.First()) - .ToList()) + var runsToKeep = cachedAnnotationInformation + .SelectMany(item => + root.Descendants() + .Where(d => + { + var stack = d.Annotation>(); + return stack != null && stack.Any(stackItem => stackItem.Id == item.Key); + }) + .Select(d => d.AncestorsAndSelf(W.r).FirstOrDefault()) + .GroupAdjacent(o => o) + .Select(g => g.First()) + .ToList() + ) .ToList(); foreach (var paragraph in root.Descendants(W.p).ToList()) { if (paragraph.Elements(W.r).Any(r => runsToKeep.Contains(r))) { - paragraph.Elements(W.r) - .Where(r => !runsToKeep.Contains(r) && - !r.Elements(W.tab).Any()) - .Remove(); - paragraph.Elements(W.r) + paragraph.Elements(W.r).Where(r => !runsToKeep.Contains(r) && !r.Elements(W.tab).Any()).Remove(); + paragraph + .Elements(W.r) .Where(r => !runsToKeep.Contains(r)) .Elements() - .Where(rc => rc.Name != W.rPr && - rc.Name != W.tab) + .Where(rc => rc.Name != W.rPr && rc.Name != W.tab) .Remove(); } else diff --git a/Clippit.Tests/Word/Samples/FormattingAssemblerSamples.cs b/Clippit.Tests/Word/Samples/FormattingAssemblerSamples.cs index 32b615f6..6cbb892d 100644 --- a/Clippit.Tests/Word/Samples/FormattingAssemblerSamples.cs +++ b/Clippit.Tests/Word/Samples/FormattingAssemblerSamples.cs @@ -8,9 +8,8 @@ namespace Clippit.Tests.Word.Samples { public class FormattingAssemblerSamples : TestsBase { - public FormattingAssemblerSamples(ITestOutputHelper log) : base(log) - { - } + public FormattingAssemblerSamples(ITestOutputHelper log) + : base(log) { } [Theory] [InlineData("Test01.docx")] @@ -20,7 +19,7 @@ public void Sample(string fileName) var file = new FileInfo(Path.Combine("../../../Word/Samples/FormattingAssembler/", fileName)); var newFile = new FileInfo(Path.Combine(TempDir, file.Name.Replace(".docx", "out.docx"))); File.Copy(file.FullName, newFile.FullName, true); - + using var wDoc = WordprocessingDocument.Open(newFile.FullName, true); var settings = new FormattingAssemblerSettings() { diff --git a/Clippit.Tests/Word/Samples/ListItemRetrieverSamples.cs b/Clippit.Tests/Word/Samples/ListItemRetrieverSamples.cs index 410d3911..6e60d5bc 100644 --- a/Clippit.Tests/Word/Samples/ListItemRetrieverSamples.cs +++ b/Clippit.Tests/Word/Samples/ListItemRetrieverSamples.cs @@ -12,21 +12,22 @@ namespace Clippit.Tests.Word.Samples { public class ListItemRetrieverSamples : TestsBase { - public ListItemRetrieverSamples(ITestOutputHelper log) : base(log) - { - } - + public ListItemRetrieverSamples(ITestOutputHelper log) + : base(log) { } + private class XmlStackItem { public XElement Element { get; init; } - public int[] LevelNumbers{ get; init; } + public int[] LevelNumbers { get; init; } } [Fact] public void Sample() { - using var wDoc = - WordprocessingDocument.Open("../../../Word/Samples/ListItemRetriever/NumberedListTest.docx", false); + using var wDoc = WordprocessingDocument.Open( + "../../../Word/Samples/ListItemRetriever/NumberedListTest.docx", + false + ); var abstractNumId = 0; var xml = ConvertDocToXml(wDoc, abstractNumId); Log.WriteLine(xml.ToString()); @@ -43,77 +44,67 @@ private static XElement ConvertDocToXml(WordprocessingDocument wDoc, int abstrac var xml = new XElement("Root"); var current = new Stack(); - current.Push(new XmlStackItem { Element = xml, LevelNumbers = Array.Empty(), }); + current.Push(new XmlStackItem { Element = xml, LevelNumbers = Array.Empty() }); foreach (var paragraph in xd.Descendants(W.p)) { // The following does not take into account documents that have tracked revisions. // As necessary, call RevisionAccepter.AcceptRevisions before converting to XML. var text = paragraph.Descendants(W.t).Select(t => (string)t).StringConcatenate(); - var lii = paragraph.Annotation(); + var lii = paragraph.Annotation(); if (lii.IsListItem && lii.AbstractNumId == abstractNumId) { - var levelNums = - paragraph.Annotation(); + var levelNums = paragraph.Annotation(); if (levelNums.LevelNumbersArray.Length == current.Peek().LevelNumbers.Length) { current.Pop(); var levelNumsForThisIndent = levelNums.LevelNumbersArray; var levelText = levelNums - .LevelNumbersArray - .Select(l => l + ".") + .LevelNumbersArray.Select(l => l + ".") .StringConcatenate() .TrimEnd('.'); - var newCurrentElement = new XElement("Indent", - new XAttribute("Level", levelText)); + var newCurrentElement = new XElement("Indent", new XAttribute("Level", levelText)); current.Peek().Element.Add(newCurrentElement); current.Push( - new XmlStackItem() { Element = newCurrentElement, LevelNumbers = levelNumsForThisIndent, }); + new XmlStackItem() { Element = newCurrentElement, LevelNumbers = levelNumsForThisIndent } + ); current.Peek().Element.Add(new XElement("Heading", text)); } else if (levelNums.LevelNumbersArray.Length > current.Peek().LevelNumbers.Length) { - for (var i = current.Peek().LevelNumbers.Length; - i < levelNums.LevelNumbersArray.Length; - i++) + for (var i = current.Peek().LevelNumbers.Length; i < levelNums.LevelNumbersArray.Length; i++) { - var levelNumsForThisIndent = levelNums - .LevelNumbersArray - .Take(i + 1) - .ToArray(); + var levelNumsForThisIndent = levelNums.LevelNumbersArray.Take(i + 1).ToArray(); var levelText = levelNums - .LevelNumbersArray - .Select(l => l + ".") + .LevelNumbersArray.Select(l => l + ".") .StringConcatenate() .TrimEnd('.'); - var newCurrentElement = new XElement("Indent", - new XAttribute("Level", levelText)); + var newCurrentElement = new XElement("Indent", new XAttribute("Level", levelText)); current.Peek().Element.Add(newCurrentElement); current.Push( new XmlStackItem() { - Element = newCurrentElement, LevelNumbers = levelNumsForThisIndent, - }); + Element = newCurrentElement, + LevelNumbers = levelNumsForThisIndent, + } + ); current.Peek().Element.Add(new XElement("Heading", text)); } } else if (levelNums.LevelNumbersArray.Length < current.Peek().LevelNumbers.Length) { - for (var i = current.Peek().LevelNumbers.Length; - i > levelNums.LevelNumbersArray.Length; - i--) + for (var i = current.Peek().LevelNumbers.Length; i > levelNums.LevelNumbersArray.Length; i--) current.Pop(); current.Pop(); var levelNumsForThisIndent = levelNums.LevelNumbersArray; var levelText = levelNums - .LevelNumbersArray - .Select(l => l + ".") + .LevelNumbersArray.Select(l => l + ".") .StringConcatenate() .TrimEnd('.'); - var newCurrentElement = new XElement("Indent", - new XAttribute("Level", levelText)); + var newCurrentElement = new XElement("Indent", new XAttribute("Level", levelText)); current.Peek().Element.Add(newCurrentElement); current.Push( - new XmlStackItem() { Element = newCurrentElement, LevelNumbers = levelNumsForThisIndent, }); + new XmlStackItem() { Element = newCurrentElement, LevelNumbers = levelNumsForThisIndent } + ); current.Peek().Element.Add(new XElement("Heading", text)); } } diff --git a/Clippit.Tests/Word/Samples/ReferenceAdderSamples.cs b/Clippit.Tests/Word/Samples/ReferenceAdderSamples.cs index 12037bc5..0f47e49e 100644 --- a/Clippit.Tests/Word/Samples/ReferenceAdderSamples.cs +++ b/Clippit.Tests/Word/Samples/ReferenceAdderSamples.cs @@ -8,10 +8,9 @@ namespace Clippit.Tests.Word.Samples { public class ReferenceAdderSamples : TestsBase { - public ReferenceAdderSamples(ITestOutputHelper log) : base(log) - { - } - + public ReferenceAdderSamples(ITestOutputHelper log) + : base(log) { } + [Theory] [InlineData("RaTest01.docx", "/w:document/w:body/w:p[1]", @"TOC \o '1-3' \h \z \u")] // Inserts a basic TOC before the first paragraph of the document [InlineData("RaTest02.docx", "/w:document/w:body/w:p[2]", @"TOC \o '1-3' \h \z \u")] // Inserts a TOC after the title of the document @@ -25,7 +24,7 @@ public void Sample(string fileName, string xPath, string switches) var srcFile = new FileInfo(Path.Combine("../../../Word/Samples/ReferenceAdder/", fileName)); var file = Path.Combine(TempDir, srcFile.Name); srcFile.CopyTo(file, true); - + using var wDoc = WordprocessingDocument.Open(file, true); ReferenceAdder.AddToc(wDoc, xPath, switches, null, null); } diff --git a/Clippit.Tests/Word/Samples/RevisionAccepterSamples.cs b/Clippit.Tests/Word/Samples/RevisionAccepterSamples.cs index a39ff01b..58680b13 100644 --- a/Clippit.Tests/Word/Samples/RevisionAccepterSamples.cs +++ b/Clippit.Tests/Word/Samples/RevisionAccepterSamples.cs @@ -7,9 +7,8 @@ namespace Clippit.Tests.Word.Samples { public class RevisionAccepterSamples : TestsBase { - public RevisionAccepterSamples(ITestOutputHelper log) : base(log) - { - } + public RevisionAccepterSamples(ITestOutputHelper log) + : base(log) { } [Fact] public void Sample() diff --git a/Clippit.Tests/Word/Samples/WmlComparerSamples.cs b/Clippit.Tests/Word/Samples/WmlComparerSamples.cs index 853a6459..692c1bfc 100644 --- a/Clippit.Tests/Word/Samples/WmlComparerSamples.cs +++ b/Clippit.Tests/Word/Samples/WmlComparerSamples.cs @@ -9,12 +9,10 @@ namespace Clippit.Tests.Word.Samples { public class WmlComparerSamples : TestsBase { - public WmlComparerSamples(ITestOutputHelper log) : base(log) - { - } - - private static string GetFilePath(string path) => - Path.Combine("../../../Word/Samples/WmlComparer/", path); + public WmlComparerSamples(ITestOutputHelper log) + : base(log) { } + + private static string GetFilePath(string path) => Path.Combine("../../../Word/Samples/WmlComparer/", path); [Fact] public void Sample1() @@ -23,7 +21,8 @@ public void Sample1() var result = WmlComparer.Compare( new WmlDocument(GetFilePath("Sample1/Source1.docx")), new WmlDocument(GetFilePath("Sample1/Source2.docx")), - settings); + settings + ); result.SaveAs(Path.Combine(TempDir, "Compared.docx")); var revisions = WmlComparer.GetRevisions(result, settings); @@ -54,12 +53,9 @@ public void Sample2() Color = Color.LightYellow, }, }; - + var settings = new WmlComparerSettings(); - var consolidatedWml = WmlComparer.Consolidate( - originalWml, - revisedDocumentInfoList, - settings); + var consolidatedWml = WmlComparer.Consolidate(originalWml, revisedDocumentInfoList, settings); consolidatedWml.SaveAs(Path.Combine(TempDir, "Consolidated.docx")); } } diff --git a/Clippit.Tests/Word/Samples/WmlToHtmlConverterSamples.cs b/Clippit.Tests/Word/Samples/WmlToHtmlConverterSamples.cs index 21ec1839..224d658d 100644 --- a/Clippit.Tests/Word/Samples/WmlToHtmlConverterSamples.cs +++ b/Clippit.Tests/Word/Samples/WmlToHtmlConverterSamples.cs @@ -11,10 +11,9 @@ namespace Clippit.Tests.Word.Samples { public class WmlToHtmlConverterSamples : TestsBase { - public WmlToHtmlConverterSamples(ITestOutputHelper log) : base(log) - { - } - + public WmlToHtmlConverterSamples(ITestOutputHelper log) + : base(log) { } + private static string RootFolder => "../../../Word/Samples/WmlToHtmlConverter/"; [Fact] @@ -30,7 +29,7 @@ private void ConvertToHtmlWithExternalFiles(string file, string outputDirectory) { var fi = new FileInfo(file); Log.WriteLine(fi.Name); - + using var memoryStream = new MemoryStream(); var byteArray = File.ReadAllBytes(fi.FullName); memoryStream.Write(byteArray, 0, byteArray.Length); @@ -69,15 +68,13 @@ private void ConvertToHtmlWithExternalFiles(string file, string outputDirectory) { ++imageCounter; return ImageHelper.DefaultImageHandler(imageInfo, imageDirectoryName, imageCounter); - } + }, }; var htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); // Produce HTML document with declaration to tell the browser // we are using HTML5. - var html = new XDocument( - new XDocumentType("html", null, null, null), - htmlElement); + var html = new XDocument(new XDocumentType("html", null, null, null), htmlElement); // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type // XEntity. PtOpenXmlUtil.cs define the XEntity class. See @@ -90,8 +87,7 @@ private void ConvertToHtmlWithExternalFiles(string file, string outputDirectory) var htmlString = html.ToString(SaveOptions.DisableFormatting); File.WriteAllText(destFileName.FullName, htmlString, Encoding.UTF8); } - - + [Fact] public void Sample2() { @@ -105,11 +101,11 @@ private void ConvertToHtmlWithEmbeddedImages(string file, string outputDirectory { var fi = new FileInfo(file); Log.WriteLine(fi.Name); - + using var memoryStream = new MemoryStream(); var byteArray = File.ReadAllBytes(fi.FullName); memoryStream.Write(byteArray, 0, byteArray.Length); - + using var wDoc = WordprocessingDocument.Open(memoryStream, true); var destFileName = new FileInfo(fi.Name.Replace(".docx", ".html")); if (!string.IsNullOrEmpty(outputDirectory)) @@ -146,7 +142,7 @@ private void ConvertToHtmlWithEmbeddedImages(string file, string outputDirectory ++imageCounter; var extension = imageInfo.ContentType.Split('/')[1].ToLower(); var imageEncoder = ImageHelper.GetEncoder(extension, out extension); - + // If the image format isn't one that we expect, ignore it, // and don't return markup for the link. if (imageEncoder is null) @@ -168,20 +164,20 @@ private void ConvertToHtmlWithEmbeddedImages(string file, string outputDirectory var mimeType = "image/" + extension; var imageSource = $"data:{mimeType};base64,{base64}"; - var img = new XElement(Xhtml.img, + var img = new XElement( + Xhtml.img, new XAttribute(NoNamespace.src, imageSource), imageInfo.ImgStyleAttribute, - imageInfo.AltText != null ? new XAttribute(NoNamespace.alt, imageInfo.AltText) : null); + imageInfo.AltText != null ? new XAttribute(NoNamespace.alt, imageInfo.AltText) : null + ); return img; - } + }, }; var htmlElement = WmlToHtmlConverter.ConvertToHtml(wDoc, settings); // Produce HTML document with declaration to tell the browser // we are using HTML5. - var html = new XDocument( - new XDocumentType("html", null, null, null), - htmlElement); + var html = new XDocument(new XDocumentType("html", null, null, null), htmlElement); // Note: the xhtml returned by ConvertToHtmlTransform contains objects of type // XEntity. PtOpenXmlUtil.cs define the XEntity class. See diff --git a/Clippit.Tests/Word/StronglyTypedBlockTests.cs b/Clippit.Tests/Word/StronglyTypedBlockTests.cs index 78d2cf0e..76adaff8 100644 --- a/Clippit.Tests/Word/StronglyTypedBlockTests.cs +++ b/Clippit.Tests/Word/StronglyTypedBlockTests.cs @@ -17,10 +17,9 @@ namespace Clippit.Tests.Word { public class StronglyTypedBlockTests : TestsBase { - public StronglyTypedBlockTests(ITestOutputHelper log) : base(log) - { - } - + public StronglyTypedBlockTests(ITestOutputHelper log) + : base(log) { } + [Fact] public void CanUseStronglyTypedBlockToDemarcateApis() { @@ -66,7 +65,6 @@ public void ConstructorThrowsWhenPassingNull() using var _ = new StronglyTypedBlock(null); }); } - } } diff --git a/Clippit.Tests/Word/WmlComparerTests.cs b/Clippit.Tests/Word/WmlComparerTests.cs index b255ba5d..78c23709 100644 --- a/Clippit.Tests/Word/WmlComparerTests.cs +++ b/Clippit.Tests/Word/WmlComparerTests.cs @@ -30,10 +30,13 @@ public class WmlComparerTests : TestsBase /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static bool s_OpenWord = false; public static bool m_OpenTempDirInExplorer = false; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Theory] - [InlineData("RC-0010", "RC/RC001-Before.docx", + [InlineData( + "RC-0010", + "RC/RC001-Before.docx", @" RC/RC001-After1.docx @@ -45,48 +48,66 @@ public class WmlComparerTests : TestsBase LightPink From Fred - ")] - [InlineData("RC-0020", "RC/RC002-Image.docx", + " + )] + [InlineData( + "RC-0020", + "RC/RC002-Image.docx", @" RC/RC002-Image-After1.docx LightBlue From Bob - ")] - [InlineData("RC-0030", "RC/RC002-Image-After1.docx", + " + )] + [InlineData( + "RC-0030", + "RC/RC002-Image-After1.docx", @" RC/RC002-Image.docx LightBlue From Bob - ")] - [InlineData("RC-0040", "WC/WC027-Twenty-Paras-Before.docx", + " + )] + [InlineData( + "RC-0040", + "WC/WC027-Twenty-Paras-Before.docx", @" WC/WC027-Twenty-Paras-After-1.docx LightBlue From Bob - ")] - [InlineData("RC-0050", "WC/WC027-Twenty-Paras-Before.docx", + " + )] + [InlineData( + "RC-0050", + "WC/WC027-Twenty-Paras-Before.docx", @" WC/WC027-Twenty-Paras-After-3.docx LightBlue From Bob - ")] - [InlineData("RC-0060", "RC/RC003-Multi-Paras.docx", + " + )] + [InlineData( + "RC-0060", + "RC/RC003-Multi-Paras.docx", @" RC/RC003-Multi-Paras-After.docx LightBlue From Bob - ")] - [InlineData("RC-0070", "RC/RC004-Before.docx", + " + )] + [InlineData( + "RC-0070", + "RC/RC004-Before.docx", @" RC/RC004-After1.docx @@ -98,32 +119,41 @@ public class WmlComparerTests : TestsBase LightPink From Fred - ")] - [InlineData("RC-0080", "RC/RC005-Before.docx", + " + )] + [InlineData( + "RC-0080", + "RC/RC005-Before.docx", @" RC/RC005-After1.docx LightYellow From Bob - ")] - [InlineData("RC-0090", "RC/RC006-Before.docx", + " + )] + [InlineData( + "RC-0090", + "RC/RC006-Before.docx", @" RC/RC006-After1.docx LightYellow From Bob - ")] - [InlineData("RC-0100", "RC/RC007-Endnotes-Before.docx", + " + )] + [InlineData( + "RC-0100", + "RC/RC007-Endnotes-Before.docx", @" RC/RC007-Endnotes-After.docx LightYellow From Bob - ")] - + " + )] public void WC001_Consolidate(string testId, string originalName, string revisedDocumentsXml) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); @@ -149,7 +179,9 @@ public void WC001_Consolidate(string testId, string originalName, string revised .Select(z => { var revisedDocx = new FileInfo(Path.Combine(sourceDir.FullName, z.Element("DocName").Value)); - var revisedCopiedToDestDocx = new FileInfo(Path.Combine(thisTestTempDir.FullName, revisedDocx.Name)); + var revisedCopiedToDestDocx = new FileInfo( + Path.Combine(thisTestTempDir.FullName, revisedDocx.Name) + ); var wml1 = new WmlDocument(revisedDocx.FullName); var wml2 = WordprocessingMLUtil.BreakLinkToTemplate(wml1); wml2.SaveAs(revisedCopiedToDestDocx.FullName); @@ -168,10 +200,7 @@ public void WC001_Consolidate(string testId, string originalName, string revised var source1Wml = new WmlDocument(originalCopiedToDestDocx.FullName); var settings = new WmlComparerSettings(); settings.DebugTempFileDi = thisTestTempDir; - var consolidatedWml = WmlComparer.Consolidate( - source1Wml, - revisedDocumentsArray, - settings); + var consolidatedWml = WmlComparer.Consolidate(source1Wml, revisedDocumentsArray, settings); var wml3 = WordprocessingMLUtil.BreakLinkToTemplate(consolidatedWml); wml3.SaveAs(consolidatedDocumentFi.FullName); @@ -185,7 +214,6 @@ public void WC001_Consolidate(string testId, string originalName, string revised var errors = validator.Validate(wDoc).Where(e => !ExpectedErrors.Contains(e.Description)); if (errors.Count() > 0) { - var ind = " "; var sb = new StringBuilder(); foreach (var err in errors) @@ -218,7 +246,9 @@ public void WC001_Consolidate(string testId, string originalName, string revised .Select(z => { var revisedDocx = new FileInfo(Path.Combine(sourceDir.FullName, z.Element("DocName").Value)); - var revisedCopiedToDestDocx = new FileInfo(Path.Combine(thisTestTempDir.FullName, revisedDocx.Name)); + var revisedCopiedToDestDocx = new FileInfo( + Path.Combine(thisTestTempDir.FullName, revisedDocx.Name) + ); return revisedCopiedToDestDocx; }) .ToList(); @@ -287,8 +317,16 @@ public void WC001_Consolidate(string testId, string originalName, string revised [InlineData("WCB-1260", "WC/WC013-Image-Before2.docx", "WC/WC013-Image-After2.docx")] [InlineData("WCB-1270", "WC/WC014-SmartArt-Before.docx", "WC/WC014-SmartArt-After.docx")] [InlineData("WCB-1280", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-After.docx")] - [InlineData("WCB-1290", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-Deleted-After.docx")] - [InlineData("WCB-1300", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-Deleted-After2.docx")] + [InlineData( + "WCB-1290", + "WC/WC014-SmartArt-With-Image-Before.docx", + "WC/WC014-SmartArt-With-Image-Deleted-After.docx" + )] + [InlineData( + "WCB-1300", + "WC/WC014-SmartArt-With-Image-Before.docx", + "WC/WC014-SmartArt-With-Image-Deleted-After2.docx" + )] [InlineData("WCB-1310", "WC/WC015-Three-Paragraphs.docx", "WC/WC015-Three-Paragraphs-After.docx")] [InlineData("WCB-1320", "WC/WC016-Para-Image-Para.docx", "WC/WC016-Para-Image-Para-w-Deleted-Image.docx")] [InlineData("WCB-1330", "WC/WC017-Image.docx", "WC/WC017-Image-After.docx")] @@ -301,7 +339,11 @@ public void WC001_Consolidate(string testId, string originalName, string revised [InlineData("WCB-1400", "WC/WC021-Math-Before-1.docx", "WC/WC021-Math-After-1.docx")] [InlineData("WCB-1410", "WC/WC021-Math-Before-2.docx", "WC/WC021-Math-After-2.docx")] [InlineData("WCB-1420", "WC/WC022-Image-Math-Para-Before.docx", "WC/WC022-Image-Math-Para-After.docx")] - [InlineData("WCB-1430", "WC/WC023-Table-4-Row-Image-Before.docx", "WC/WC023-Table-4-Row-Image-After-Delete-1-Row.docx")] + [InlineData( + "WCB-1430", + "WC/WC023-Table-4-Row-Image-Before.docx", + "WC/WC023-Table-4-Row-Image-After-Delete-1-Row.docx" + )] [InlineData("WCB-1440", "WC/WC024-Table-Before.docx", "WC/WC024-Table-After.docx")] [InlineData("WCB-1450", "WC/WC024-Table-Before.docx", "WC/WC024-Table-After2.docx")] [InlineData("WCB-1460", "WC/WC025-Simple-Table-Before.docx", "WC/WC025-Simple-Table-After.docx")] @@ -376,15 +418,21 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name var source1DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name1)); var source2DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name2)); - var source1CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx"))); - var source2CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx"))); + var source1CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx")) + ); + var source2CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx")) + ); if (!source1CopiedToDestDocxForWord.Exists) File.Copy(source1Docx.FullName, source1CopiedToDestDocxForWord.FullName); if (!source2CopiedToDestDocxForWord.Exists) File.Copy(source2Docx.FullName, source2CopiedToDestDocxForWord.FullName); var wordExe = new FileInfo(@"C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE"); - var path = new DirectoryInfo(@"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles"); + var path = new DirectoryInfo( + @"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles" + ); WordRunner.RunWord(wordExe, source2CopiedToDestDocxForWord); WordRunner.RunWord(wordExe, source1CopiedToDestDocxForWord); } @@ -393,8 +441,12 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name var before = source1CopiedToDestDocx.Name.Replace(".docx", ""); var after = source2CopiedToDestDocx.Name.Replace(".docx", ""); - var docxWithRevisionsFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx")); - var docxConsolidatedFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, before + "-CONSOLIDATED-" + after + ".docx")); + var docxWithRevisionsFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx") + ); + var docxConsolidatedFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, before + "-CONSOLIDATED-" + after + ".docx") + ); var source1Wml = new WmlDocument(source1CopiedToDestDocx.FullName); var source2Wml = new WmlDocument(source2CopiedToDestDocx.FullName); @@ -409,12 +461,9 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name RevisedDocument = source2Wml, Color = Color.LightBlue, Revisor = "Revised by Eric White", - } + }, }; - var consolidatedWml = WmlComparer.Consolidate( - source1Wml, - revisedDocInfo, - settings); + var consolidatedWml = WmlComparer.Consolidate(source1Wml, revisedDocInfo, settings); WordprocessingMLUtil.BreakLinkToTemplate(consolidatedWml).SaveAs(docxConsolidatedFi.FullName); var validationErrors = ""; @@ -427,7 +476,6 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name var errors = validator.Validate(wDoc).Where(e => !ExpectedErrors.Contains(e.Description)); if (errors.Count() > 0) { - var ind = " "; var sb = new StringBuilder(); foreach (var err in errors) @@ -514,9 +562,24 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name [InlineData("WC-1250", "WC/WC013-Image-Before.docx", "WC/WC013-Image-After2.docx", 2)] [InlineData("WC-1260", "WC/WC013-Image-Before2.docx", "WC/WC013-Image-After2.docx", 2)] [InlineData("WC-1270", "WC/WC014-SmartArt-Before.docx", "WC/WC014-SmartArt-After.docx", 2)] - [InlineData("WC-1280", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-After.docx", 2)] - [InlineData("WC-1310", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-Deleted-After.docx", 3)] - [InlineData("WC-1320", "WC/WC014-SmartArt-With-Image-Before.docx", "WC/WC014-SmartArt-With-Image-Deleted-After2.docx", 1)] + [InlineData( + "WC-1280", + "WC/WC014-SmartArt-With-Image-Before.docx", + "WC/WC014-SmartArt-With-Image-After.docx", + 2 + )] + [InlineData( + "WC-1310", + "WC/WC014-SmartArt-With-Image-Before.docx", + "WC/WC014-SmartArt-With-Image-Deleted-After.docx", + 3 + )] + [InlineData( + "WC-1320", + "WC/WC014-SmartArt-With-Image-Before.docx", + "WC/WC014-SmartArt-With-Image-Deleted-After2.docx", + 1 + )] [InlineData("WC-1330", "WC/WC015-Three-Paragraphs.docx", "WC/WC015-Three-Paragraphs-After.docx", 3)] [InlineData("WC-1340", "WC/WC016-Para-Image-Para.docx", "WC/WC016-Para-Image-Para-w-Deleted-Image.docx", 1)] [InlineData("WC-1350", "WC/WC017-Image.docx", "WC/WC017-Image-After.docx", 3)] @@ -529,7 +592,12 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name [InlineData("WC-1420", "WC/WC021-Math-Before-1.docx", "WC/WC021-Math-After-1.docx", 9)] [InlineData("WC-1430", "WC/WC021-Math-Before-2.docx", "WC/WC021-Math-After-2.docx", 6)] [InlineData("WC-1440", "WC/WC022-Image-Math-Para-Before.docx", "WC/WC022-Image-Math-Para-After.docx", 10)] - [InlineData("WC-1450", "WC/WC023-Table-4-Row-Image-Before.docx", "WC/WC023-Table-4-Row-Image-After-Delete-1-Row.docx", 7)] + [InlineData( + "WC-1450", + "WC/WC023-Table-4-Row-Image-Before.docx", + "WC/WC023-Table-4-Row-Image-After-Delete-1-Row.docx", + 7 + )] [InlineData("WC-1460", "WC/WC024-Table-Before.docx", "WC/WC024-Table-After.docx", 1)] [InlineData("WC-1470", "WC/WC024-Table-Before.docx", "WC/WC024-Table-After2.docx", 7)] [InlineData("WC-1480", "WC/WC025-Simple-Table-Before.docx", "WC/WC025-Simple-Table-After.docx", 4)] @@ -548,8 +616,18 @@ public void WC002_Consolidate_Bulk_Test(string testId, string name1, string name [InlineData("WC-1630", "WC/WC034-Footnotes-After3.docx", "WC/WC034-Footnotes-Before.docx", 3)] [InlineData("WC-1640", "WC/WC035-Footnote-Before.docx", "WC/WC035-Footnote-After.docx", 2)] [InlineData("WC-1650", "WC/WC035-Footnote-After.docx", "WC/WC035-Footnote-Before.docx", 2)] - [InlineData("WC-1660", "WC/WC036-Footnote-With-Table-Before.docx", "WC/WC036-Footnote-With-Table-After.docx", 5)] - [InlineData("WC-1670", "WC/WC036-Footnote-With-Table-After.docx", "WC/WC036-Footnote-With-Table-Before.docx", 5)] + [InlineData( + "WC-1660", + "WC/WC036-Footnote-With-Table-Before.docx", + "WC/WC036-Footnote-With-Table-After.docx", + 5 + )] + [InlineData( + "WC-1670", + "WC/WC036-Footnote-With-Table-After.docx", + "WC/WC036-Footnote-With-Table-Before.docx", + 5 + )] [InlineData("WC-1680", "WC/WC034-Endnotes-Before.docx", "WC/WC034-Endnotes-After1.docx", 1)] [InlineData("WC-1700", "WC/WC034-Endnotes-Before.docx", "WC/WC034-Endnotes-After2.docx", 4)] [InlineData("WC-1710", "WC/WC034-Endnotes-Before.docx", "WC/WC034-Endnotes-After3.docx", 7)] @@ -619,7 +697,9 @@ public void WC003_Compare(string testId, string name1, string name2, int revisio var before = source1CopiedToDestDocx.Name.Replace(".docx", ""); var after = source2CopiedToDestDocx.Name.Replace(".docx", ""); //var baselineDocxWithRevisionsFi = new FileInfo(Path.Combine(source1Docx.DirectoryName, before + "-COMPARE-" + after + ".docx")); - var docxWithRevisionsFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx")); + var docxWithRevisionsFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx") + ); /************************************************************************************************************************/ @@ -628,13 +708,19 @@ public void WC003_Compare(string testId, string name1, string name2, int revisio var source1DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name1)); var source2DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name2)); - var source1CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx"))); - var source2CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx"))); + var source1CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx")) + ); + var source2CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx")) + ); File.Copy(source1Docx.FullName, source1CopiedToDestDocxForWord.FullName); File.Copy(source2Docx.FullName, source2CopiedToDestDocxForWord.FullName); var wordExe = new FileInfo(@"C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE"); - var path = new DirectoryInfo(@"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles"); + var path = new DirectoryInfo( + @"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles" + ); WordRunner.RunWord(wordExe, source2CopiedToDestDocxForWord); WordRunner.RunWord(wordExe, source1CopiedToDestDocxForWord); } @@ -686,7 +772,6 @@ public void WC003_Compare(string testId, string name1, string name2, int revisio var errors = validator.Validate(wDoc).Where(e => !ExpectedErrors.Contains(e.Description)); if (errors.Count() > 0) { - var ind = " "; var sb = new StringBuilder(); foreach (var err in errors) @@ -768,7 +853,9 @@ public void WC003_Compare(string testId, string name1, string name2, int revisio if (WRITE_TEMP_FILES) { - var afterRejectingComparedFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, "AfterRejectingCompared.docx")); + var afterRejectingComparedFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, "AfterRejectingCompared.docx") + ); afterRejectingComparedWml.SaveAs(afterRejectingComparedFi.FullName); } @@ -785,7 +872,9 @@ public void WC003_Compare(string testId, string name1, string name2, int revisio if (WRITE_TEMP_FILES) { - var afterAcceptingComparedFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, "AfterAcceptingCompared.docx")); + var afterAcceptingComparedFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, "AfterAcceptingCompared.docx") + ); afterAcceptingComparedWml.SaveAs(afterAcceptingComparedFi.FullName); } @@ -834,8 +923,8 @@ public void WC003_Throws(string name1, string name2, int revisionCount) [InlineData("WCS-1090", "WC/WC002-InsertAtEnd.docx")] [InlineData("WCS-1100", "WC/WC002-InsertInMiddle.docx")] [InlineData("WCS-1110", "WC/WC002-Unmodified.docx")] - //[InlineData("WCS-1120", "WC/WC004-Large.docx")] - //[InlineData("WCS-1130", "WC/WC004-Large-Mod.docx")] + //[InlineData("WCS-1120", "WC/WC004-Large.docx")] + //[InlineData("WCS-1130", "WC/WC004-Large-Mod.docx")] [InlineData("WCS-1140", "WC/WC006-Table.docx")] [InlineData("WCS-1150", "WC/WC006-Table-Delete-Contests-of-Row.docx")] [InlineData("WCS-1160", "WC/WC006-Table-Delete-Row.docx")] @@ -880,10 +969,10 @@ public void WC003_Throws(string name1, string name2, int revisionCount) [InlineData("WCS-1550", "WC/WC021-Math-Before-1.docx")] [InlineData("WCS-1560", "WC/WC022-Image-Math-Para-After.docx")] [InlineData("WCS-1570", "WC/WC022-Image-Math-Para-Before.docx")] - //[InlineData("WCS-1580", "", "")] - //[InlineData("WCS-1590", "", "")] - //[InlineData("WCS-1600", "", "")] - //[InlineData("WCS-1610", "", "")] + //[InlineData("WCS-1580", "", "")] + //[InlineData("WCS-1590", "", "")] + //[InlineData("WCS-1600", "", "")] + //[InlineData("WCS-1610", "", "")] public void WC004_Compare_To_Self(string testId, string name) { @@ -896,7 +985,9 @@ public void WC004_Compare_To_Self(string testId, string name) else thisTestTempDir.Create(); - var sourceCopiedToDestDocx = new FileInfo(Path.Combine(thisTestTempDir.FullName, sourceDocx.Name.Replace(".docx", "-Source.docx"))); + var sourceCopiedToDestDocx = new FileInfo( + Path.Combine(thisTestTempDir.FullName, sourceDocx.Name.Replace(".docx", "-Source.docx")) + ); if (!sourceCopiedToDestDocx.Exists) File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); @@ -919,7 +1010,6 @@ public void WC004_Compare_To_Self(string testId, string name) [Theory] [InlineData("WCI-1000", "WC/WC040-Case-Before.docx", "WC/WC040-Case-After.docx", 2)] - public void WC005_Compare_CaseInsensitive(string testId, string name1, string name2, int revisionCount) { var sourceDir = new DirectoryInfo("../../../../TestFiles/"); @@ -946,15 +1036,21 @@ public void WC005_Compare_CaseInsensitive(string testId, string name1, string na var source1DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name1)); var source2DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name2)); - var source1CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx"))); - var source2CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx"))); + var source1CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx")) + ); + var source2CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx")) + ); if (!source1CopiedToDestDocxForWord.Exists) File.Copy(source1Docx.FullName, source1CopiedToDestDocxForWord.FullName); if (!source2CopiedToDestDocxForWord.Exists) File.Copy(source2Docx.FullName, source2CopiedToDestDocxForWord.FullName); var wordExe = new FileInfo(@"C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE"); - var path = new DirectoryInfo(@"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles"); + var path = new DirectoryInfo( + @"C:\Users\Eric\Documents\WindowsPowerShellModules\Open-Xml-PowerTools\TestFiles" + ); WordRunner.RunWord(wordExe, source2CopiedToDestDocxForWord); WordRunner.RunWord(wordExe, source1CopiedToDestDocxForWord); } @@ -963,7 +1059,9 @@ public void WC005_Compare_CaseInsensitive(string testId, string name1, string na var before = source1CopiedToDestDocx.Name.Replace(".docx", ""); var after = source2CopiedToDestDocx.Name.Replace(".docx", ""); - var docxWithRevisionsFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx")); + var docxWithRevisionsFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx") + ); var source1Wml = new WmlDocument(source1CopiedToDestDocx.FullName); var source2Wml = new WmlDocument(source2CopiedToDestDocx.FullName); @@ -982,7 +1080,6 @@ public void WC005_Compare_CaseInsensitive(string testId, string name1, string na var errors = validator.Validate(wDoc).Where(e => !ExpectedErrors.Contains(e.Description)); if (errors.Any()) { - var ind = " "; var sb = new StringBuilder(); foreach (var err in errors) @@ -1040,14 +1137,14 @@ private static void ValidateDocument(WmlDocument wmlToValidate) #else sb.Append(" \"" + err.Description + "\"," + Environment.NewLine); #endif - } var sbs = sb.ToString(); Assert.Equal("", sbs); } } - public static string[] ExpectedErrors = new string[] { + public static string[] ExpectedErrors = new string[] + { "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", @@ -1075,9 +1172,8 @@ private static void ValidateDocument(WmlDocument wmlToValidate) "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:fill' attribute is invalid - The value '0' is not valid according to any of the memberTypes of the union.", }; - public WmlComparerTests(ITestOutputHelper log) : base(log) - { - } + public WmlComparerTests(ITestOutputHelper log) + : base(log) { } } public class WordRunner diff --git a/Clippit.Tests/Word/WmlComparerTests2.cs b/Clippit.Tests/Word/WmlComparerTests2.cs index 97347bc0..9cb55aa0 100644 --- a/Clippit.Tests/Word/WmlComparerTests2.cs +++ b/Clippit.Tests/Word/WmlComparerTests2.cs @@ -17,20 +17,25 @@ namespace Clippit.Tests.Word { public class WmlComparerTests2 : TestsBase { - public WmlComparerTests2(ITestOutputHelper log) : base(log) - { - } - + public WmlComparerTests2(ITestOutputHelper log) + : base(log) { } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static bool m_OpenWord = false; public static bool m_OpenTempDirInExplorer = false; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Theory] [InlineData("CZ-1000", "CZ/CZ001-Plain.docx", "CZ/CZ001-Plain-Mod.docx", 1)] [InlineData("CZ-1010", "CZ/CZ002-Multi-Paragraphs.docx", "CZ/CZ002-Multi-Paragraphs-Mod.docx", 1)] [InlineData("CZ-1020", "CZ/CZ003-Multi-Paragraphs.docx", "CZ/CZ003-Multi-Paragraphs-Mod.docx", 1)] - [InlineData("CZ-1030", "CZ/CZ004-Multi-Paragraphs-in-Cell.docx", "CZ/CZ004-Multi-Paragraphs-in-Cell-Mod.docx", 1)] + [InlineData( + "CZ-1030", + "CZ/CZ004-Multi-Paragraphs-in-Cell.docx", + "CZ/CZ004-Multi-Paragraphs-in-Cell-Mod.docx", + 1 + )] public void CZ001_CompareTrackedInPrev(string testId, string name1, string name2, int revisionCount) { // TODO: Do we need to keep the revision count parameter? @@ -57,8 +62,12 @@ public void CZ001_CompareTrackedInPrev(string testId, string name1, string name2 var source1DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name1)); var source2DocxForWord = new FileInfo(Path.Combine(sourceDir.FullName, name2)); - var source1CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx"))); - var source2CopiedToDestDocxForWord = new FileInfo(Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx"))); + var source1CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source1Docx.Name.Replace(".docx", "-For-Word.docx")) + ); + var source2CopiedToDestDocxForWord = new FileInfo( + Path.Combine(thisTestTempDir.FullName, source2Docx.Name.Replace(".docx", "-For-Word.docx")) + ); if (!source1CopiedToDestDocxForWord.Exists) File.Copy(source1Docx.FullName, source1CopiedToDestDocxForWord.FullName); if (!source2CopiedToDestDocxForWord.Exists) @@ -73,7 +82,9 @@ public void CZ001_CompareTrackedInPrev(string testId, string name1, string name2 var before = source1CopiedToDestDocx.Name.Replace(".docx", ""); var after = source2CopiedToDestDocx.Name.Replace(".docx", ""); - var docxWithRevisionsFi = new FileInfo(Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx")); + var docxWithRevisionsFi = new FileInfo( + Path.Combine(thisTestTempDir.FullName, before + "-COMPARE-" + after + ".docx") + ); var source1Wml = new WmlDocument(source1CopiedToDestDocx.FullName); var source2Wml = new WmlDocument(source2CopiedToDestDocx.FullName); @@ -91,7 +102,6 @@ public void CZ001_CompareTrackedInPrev(string testId, string name1, string name2 var errors = validator.Validate(wDoc).Where(e => !ExpectedErrors.Contains(e.Description)); if (errors.Any()) { - var ind = " "; var sb = new StringBuilder(); foreach (var err in errors) @@ -924,7 +934,8 @@ private static void ValidateDocument(WmlDocument wmlToValidate) } } - public static string[] ExpectedErrors = new string[] { + public static string[] ExpectedErrors = new string[] + { "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstRow' attribute is not declared.", "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:lastRow' attribute is not declared.", "The 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:firstColumn' attribute is not declared.", diff --git a/Clippit.Tests/Word/WmlContentAtomListTests.cs b/Clippit.Tests/Word/WmlContentAtomListTests.cs index 2f17c271..bc6d3061 100644 --- a/Clippit.Tests/Word/WmlContentAtomListTests.cs +++ b/Clippit.Tests/Word/WmlContentAtomListTests.cs @@ -15,10 +15,9 @@ namespace Clippit.Tests.Word { public class WmlContentAtomListTests : TestsBase { - public WmlContentAtomListTests(ITestOutputHelper log) : base(log) - { - } - + public WmlContentAtomListTests(ITestOutputHelper log) + : base(log) { } + /* * This test was removed because it depends on the Coalesce method, which is only ever used * by this test. @@ -92,11 +91,15 @@ public void CA002_Annotations(string name) var sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); #if COPY_FILES_FOR_DEBUGGING - var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-1-Source.docx"))); + var sourceCopiedToDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-1-Source.docx")) + ); if (!sourceCopiedToDestDocx.Exists) File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); - var annotatedDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-2-Annotated.docx"))); + var annotatedDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", "-2-Annotated.docx")) + ); if (!annotatedDocx.Exists) File.Copy(sourceDocx.FullName, annotatedDocx.FullName); @@ -118,18 +121,21 @@ public void CA003_ContentAtoms_Throws(string name) var sourceDir = new DirectoryInfo("../../../../TestFiles/"); var sourceDocx = new FileInfo(Path.Combine(sourceDir.FullName, name)); var thisGuid = Guid.NewGuid().ToString().Replace("-", ""); - var sourceCopiedToDestDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", - $"-{thisGuid}-1-Source.docx"))); + var sourceCopiedToDestDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", $"-{thisGuid}-1-Source.docx")) + ); if (!sourceCopiedToDestDocx.Exists) File.Copy(sourceDocx.FullName, sourceCopiedToDestDocx.FullName); - var coalescedDocx = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", - $"-{thisGuid}-2-Coalesced.docx"))); + var coalescedDocx = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", $"-{thisGuid}-2-Coalesced.docx")) + ); if (!coalescedDocx.Exists) File.Copy(sourceDocx.FullName, coalescedDocx.FullName); - var contentAtomDataFi = new FileInfo(Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", - $"-{thisGuid}-3-ContentAtomData.txt"))); + var contentAtomDataFi = new FileInfo( + Path.Combine(TempDir, sourceDocx.Name.Replace(".docx", $"-{thisGuid}-3-ContentAtomData.txt")) + ); using var wDoc = WordprocessingDocument.Open(coalescedDocx.FullName, true); Assert.Throws(() => @@ -139,7 +145,6 @@ public void CA003_ContentAtoms_Throws(string name) WmlComparer.CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings); }); } - } } diff --git a/Clippit/Comparer/ComparisonUnit.cs b/Clippit/Comparer/ComparisonUnit.cs index 8383d5f2..4f494c7d 100644 --- a/Clippit/Comparer/ComparisonUnit.cs +++ b/Clippit/Comparer/ComparisonUnit.cs @@ -22,10 +22,11 @@ public int DescendantContentAtomsCount { get { - if (_descendantContentAtomsCount != null) return (int) _descendantContentAtomsCount; + if (_descendantContentAtomsCount != null) + return (int)_descendantContentAtomsCount; _descendantContentAtomsCount = DescendantContentAtoms().Count(); - return (int) _descendantContentAtomsCount; + return (int)_descendantContentAtomsCount; } } @@ -41,9 +42,7 @@ public IEnumerable DescendantContentAtoms() return Descendants().OfType(); } - private static void DescendantsInternal( - ComparisonUnit comparisonUnit, - List comparisonUnitList) + private static void DescendantsInternal(ComparisonUnit comparisonUnit, List comparisonUnitList) { foreach (var cu in comparisonUnit.Contents) { @@ -59,7 +58,8 @@ internal static string ComparisonUnitListToString(ComparisonUnit[] cul) { var sb = new StringBuilder(); sb.Append("Dump Comparision Unit List To String" + Environment.NewLine); - foreach (var item in cul) sb.Append(item.ToString(2) + Environment.NewLine); + foreach (var item in cul) + sb.Append(item.ToString(2) + Environment.NewLine); return sb.ToString(); } diff --git a/Clippit/Comparer/ComparisonUnitAtom.cs b/Clippit/Comparer/ComparisonUnitAtom.cs index 8449d149..4ece8666 100644 --- a/Clippit/Comparer/ComparisonUnitAtom.cs +++ b/Clippit/Comparer/ComparisonUnitAtom.cs @@ -15,7 +15,8 @@ public ComparisonUnitAtom( XElement contentElement, XElement[] ancestorElements, OpenXmlPart part, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { ContentElement = contentElement; AncestorElements = ancestorElements; @@ -38,7 +39,7 @@ public ComparisonUnitAtom( } } - var sha1Hash = (string) contentElement.Attribute(PtOpenXml.SHA1Hash); + var sha1Hash = (string)contentElement.Attribute(PtOpenXml.SHA1Hash); if (sha1Hash != null) { SHA1Hash = sha1Hash; @@ -81,7 +82,8 @@ private static string GetSha1HashStringForElement(XElement contentElement, WmlCo private static XElement GetRevisionTrackingElementFromAncestors( XElement contentElement, - IEnumerable ancestors) + IEnumerable ancestors + ) { return contentElement.Name == W.pPr ? contentElement.Elements(W.rPr).Elements().FirstOrDefault(e => e.Name == W.del || e.Name == W.ins) @@ -110,13 +112,15 @@ public override string ToString(int indent) if (ContentElement.Name == W.t || ContentElement.Name == W.delText) { sb.Append( - $"Atom {PadLocalName(XNamePad, this)}: {ContentElement.Value} {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} "); + $"Atom {PadLocalName(XNamePad, this)}: {ContentElement.Value} {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} " + ); AppendAncestorsDump(sb, this); } else { sb.Append( - $"Atom {PadLocalName(XNamePad, this)}: {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} "); + $"Atom {PadLocalName(XNamePad, this)}: {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} " + ); AppendAncestorsDump(sb, this); } @@ -146,14 +150,16 @@ private string ToStringAncestorUnids(int indent) if (ContentElement.Name == W.t || ContentElement.Name == W.delText) { sb.Append( - $"Atom {PadLocalName(xNamePad, this)}: {ContentElement.Value} {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} "); + $"Atom {PadLocalName(xNamePad, this)}: {ContentElement.Value} {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} " + ); AppendAncestorsUnidsDump(sb, this); } else { sb.Append( - $"Atom {PadLocalName(xNamePad, this)}: {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} "); + $"Atom {PadLocalName(xNamePad, this)}: {correlationStatus} SHA1:{SHA1Hash.Substring(0, 8)} " + ); AppendAncestorsUnidsDump(sb, this); } @@ -178,22 +184,22 @@ private static void AppendAncestorsDump(StringBuilder sb, ComparisonUnitAtom sr) private static void AppendAncestorsUnidsDump(StringBuilder sb, ComparisonUnitAtom sr) { - var zipped = sr.AncestorElements.Zip(sr.AncestorUnids, (a, u) => new - { - AncestorElement = a, - AncestorUnid = u - }); + var zipped = sr.AncestorElements.Zip( + sr.AncestorUnids, + (a, u) => new { AncestorElement = a, AncestorUnid = u } + ); var s = zipped .Select(p => p.AncestorElement.Name.LocalName + "[" + p.AncestorUnid.Substring(0, 8) + "]/") - .StringConcatenate().TrimEnd('/'); + .StringConcatenate() + .TrimEnd('/'); sb.Append("Ancestors:" + s); } private static string GetUnid(XElement p) { - var unid = (string) p.Attribute(PtOpenXml.Unid); + var unid = (string)p.Attribute(PtOpenXml.Unid); return unid == null ? "" : "[" + unid.Substring(0, 8) + "]"; } } diff --git a/Clippit/Comparer/ComparisonUnitGroup.cs b/Clippit/Comparer/ComparisonUnitGroup.cs index d651b337..a332a0b2 100644 --- a/Clippit/Comparer/ComparisonUnitGroup.cs +++ b/Clippit/Comparer/ComparisonUnitGroup.cs @@ -13,7 +13,8 @@ internal class ComparisonUnitGroup : ComparisonUnit public ComparisonUnitGroup( IEnumerable comparisonUnitList, ComparisonUnitGroupType groupType, - int level) + int level + ) { Contents = comparisonUnitList.ToList(); ComparisonUnitGroupType = groupType; @@ -21,16 +22,18 @@ public ComparisonUnitGroup( var comparisonUnitAtom = GetFirstComparisonUnitAtomOfGroup(first); var ancestorsToLookAt = comparisonUnitAtom - .AncestorElements - .Where(e => e.Name == W.tbl || e.Name == W.tr || e.Name == W.tc || e.Name == W.p || e.Name == W.txbxContent) + .AncestorElements.Where(e => + e.Name == W.tbl || e.Name == W.tr || e.Name == W.tc || e.Name == W.p || e.Name == W.txbxContent + ) .ToArray(); var ancestor = ancestorsToLookAt[level]; - if (ancestor == null) throw new OpenXmlPowerToolsException("Internal error: ComparisonUnitGroup"); + if (ancestor == null) + throw new OpenXmlPowerToolsException("Internal error: ComparisonUnitGroup"); - SHA1Hash = (string) ancestor.Attribute(PtOpenXml.SHA1Hash); - CorrelatedSHA1Hash = (string) ancestor.Attribute(PtOpenXml.CorrelatedSHA1Hash); - StructureSHA1Hash = (string) ancestor.Attribute(PtOpenXml.StructureSHA1Hash); + SHA1Hash = (string)ancestor.Attribute(PtOpenXml.SHA1Hash); + CorrelatedSHA1Hash = (string)ancestor.Attribute(PtOpenXml.CorrelatedSHA1Hash); + StructureSHA1Hash = (string)ancestor.Attribute(PtOpenXml.StructureSHA1Hash); } public ComparisonUnitGroupType ComparisonUnitGroupType { get; } @@ -55,7 +58,7 @@ private static ComparisonUnitAtom GetFirstComparisonUnitAtomOfGroup(ComparisonUn throw new OpenXmlPowerToolsException("Internal error: GetFirstComparisonUnitAtomOfGroup"); } - var ca = (ComparisonUnitAtom) tw.Contents.First(); + var ca = (ComparisonUnitAtom)tw.Contents.First(); return ca; } } @@ -63,7 +66,14 @@ private static ComparisonUnitAtom GetFirstComparisonUnitAtomOfGroup(ComparisonUn public override string ToString(int indent) { var sb = new StringBuilder(); - sb.Append("".PadRight(indent) + "Group Type: " + ComparisonUnitGroupType + " SHA1:" + SHA1Hash + Environment.NewLine); + sb.Append( + "".PadRight(indent) + + "Group Type: " + + ComparisonUnitGroupType + + " SHA1:" + + SHA1Hash + + Environment.NewLine + ); foreach (var comparisonUnitAtom in Contents) { diff --git a/Clippit/Comparer/ComparisonUnitWord.cs b/Clippit/Comparer/ComparisonUnitWord.cs index 04487e34..8072dc0e 100644 --- a/Clippit/Comparer/ComparisonUnitWord.cs +++ b/Clippit/Comparer/ComparisonUnitWord.cs @@ -44,7 +44,7 @@ internal class ComparisonUnitWord : ComparisonUnit W.sourceFileName, W.src, W.subDoc, - WNE.toolbarData + WNE.toolbarData, }; public static readonly XName[] RelationshipAttributeNames = @@ -57,7 +57,7 @@ internal class ComparisonUnitWord : ComparisonUnit R.lo, R.qs, R.href, - R.pict + R.pict, }; public ComparisonUnitWord(IEnumerable comparisonUnitAtomList) diff --git a/Clippit/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs b/Clippit/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs index 77a1fbe2..09d0456f 100644 --- a/Clippit/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs +++ b/Clippit/Comparer/WmlComparer.Internal.Methods.ComparisonUnits.cs @@ -17,7 +17,8 @@ public static partial class WmlComparer internal static ComparisonUnitAtom[] CreateComparisonUnitAtomList( OpenXmlPart part, XElement contentParent, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { VerifyNoInvalidContent(contentParent); AssignUnidToAllElements(contentParent); // add the Guid id to every element @@ -73,7 +74,8 @@ private static void MoveLastSectPrIntoLastParagraph(XElement contentParent) private static List CreateComparisonUnitAtomListInternal( OpenXmlPart part, XElement contentParent, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var comparisonUnitAtomList = new List(); CreateComparisonUnitAtomListRecurse(part, contentParent, comparisonUnitAtomList, settings); @@ -84,7 +86,8 @@ private static void CreateComparisonUnitAtomListRecurse( OpenXmlPart part, XElement element, List comparisonUnitAtomList, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { if (element.Name == W.body || element.Name == W.footnote || element.Name == W.endnote) { @@ -95,9 +98,7 @@ private static void CreateComparisonUnitAtomListRecurse( if (element.Name == W.p) { - var paraChildrenToProcess = element - .Elements() - .Where(e => e.Name != W.pPr); + var paraChildrenToProcess = element.Elements().Where(e => e.Name != W.pPr); foreach (var item in paraChildrenToProcess) CreateComparisonUnitAtomListRecurse(part, item, comparisonUnitAtomList, settings); var paraProps = element.Element(W.pPr); @@ -105,22 +106,28 @@ private static void CreateComparisonUnitAtomListRecurse( { var pPrComparisonUnitAtom = new ComparisonUnitAtom( new XElement(W.pPr), - element.AncestorsAndSelf() - .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes).Reverse() + element + .AncestorsAndSelf() + .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes) + .Reverse() .ToArray(), part, - settings); + settings + ); comparisonUnitAtomList.Add(pPrComparisonUnitAtom); } else { var pPrComparisonUnitAtom = new ComparisonUnitAtom( paraProps, - element.AncestorsAndSelf() - .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes).Reverse() + element + .AncestorsAndSelf() + .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes) + .Reverse() .ToArray(), part, - settings); + settings + ); comparisonUnitAtomList.Add(pPrComparisonUnitAtom); } @@ -129,9 +136,7 @@ private static void CreateComparisonUnitAtomListRecurse( if (element.Name == W.r) { - var runChildrenToProcess = element - .Elements() - .Where(e => e.Name != W.rPr); + var runChildrenToProcess = element.Elements().Where(e => e.Name != W.rPr); foreach (var item in runChildrenToProcess) CreateComparisonUnitAtomListRecurse(part, item, comparisonUnitAtomList, settings); return; @@ -144,11 +149,14 @@ private static void CreateComparisonUnitAtomListRecurse( { var sr = new ComparisonUnitAtom( new XElement(element.Name, ch), - element.AncestorsAndSelf() - .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes).Reverse() + element + .AncestorsAndSelf() + .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes) + .Reverse() .ToArray(), part, - settings); + settings + ); comparisonUnitAtomList.Add(sr); } @@ -159,10 +167,14 @@ private static void CreateComparisonUnitAtomListRecurse( { var sr3 = new ComparisonUnitAtom( element, - element.AncestorsAndSelf().TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes) - .Reverse().ToArray(), + element + .AncestorsAndSelf() + .TakeWhile(a => a.Name != W.body && a.Name != W.footnotes && a.Name != W.endnotes) + .Reverse() + .ToArray(), part, - settings); + settings + ); comparisonUnitAtomList.Add(sr3); return; } @@ -185,15 +197,14 @@ private static void AnnotateElementWithProps( XElement element, List comparisonUnitAtomList, XName[] childElementPropertyNames, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { IEnumerable runChildrenToProcess; if (childElementPropertyNames == null) runChildrenToProcess = element.Elements(); else - runChildrenToProcess = element - .Elements() - .Where(e => !childElementPropertyNames.Contains(e.Name)); + runChildrenToProcess = element.Elements().Where(e => !childElementPropertyNames.Contains(e.Name)); foreach (var item in runChildrenToProcess) CreateComparisonUnitAtomListRecurse(part, item, comparisonUnitAtomList, settings); @@ -207,54 +218,68 @@ private static void AnnotateElementWithProps( // into its own class. private static ComparisonUnit[] GetComparisonUnitList( ComparisonUnitAtom[] comparisonUnitAtomList, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var seed = new Atgbw { Key = null, ComparisonUnitAtomMember = null, - NextIndex = 0 + NextIndex = 0, }; IEnumerable groupingKey = comparisonUnitAtomList - .Rollup(seed, (sr, prevAtgbw, i) => - { - int? key; - var nextIndex = prevAtgbw.NextIndex; - if (sr.ContentElement.Name == W.t) + .Rollup( + seed, + (sr, prevAtgbw, i) => { - var chr = sr.ContentElement.Value; - var ch = chr[0]; - if (ch is '.' or ',') + int? key; + var nextIndex = prevAtgbw.NextIndex; + if (sr.ContentElement.Name == W.t) { - var beforeIsDigit = false; - if (i > 0) - { - var prev = comparisonUnitAtomList[i - 1]; - if (prev.ContentElement.Name == W.t && char.IsDigit(prev.ContentElement.Value[0])) - beforeIsDigit = true; - } - - var afterIsDigit = false; - if (i < comparisonUnitAtomList.Length - 1) + var chr = sr.ContentElement.Value; + var ch = chr[0]; + if (ch is '.' or ',') { - var next = comparisonUnitAtomList[i + 1]; - if (next.ContentElement.Name == W.t && char.IsDigit(next.ContentElement.Value[0])) - afterIsDigit = true; + var beforeIsDigit = false; + if (i > 0) + { + var prev = comparisonUnitAtomList[i - 1]; + if (prev.ContentElement.Name == W.t && char.IsDigit(prev.ContentElement.Value[0])) + beforeIsDigit = true; + } + + var afterIsDigit = false; + if (i < comparisonUnitAtomList.Length - 1) + { + var next = comparisonUnitAtomList[i + 1]; + if (next.ContentElement.Name == W.t && char.IsDigit(next.ContentElement.Value[0])) + afterIsDigit = true; + } + + if (beforeIsDigit || afterIsDigit) + { + key = nextIndex; + } + else + { + nextIndex++; + key = nextIndex; + nextIndex++; + } } - - if (beforeIsDigit || afterIsDigit) + else if (settings.WordSeparators.Contains(ch)) { + nextIndex++; key = nextIndex; + nextIndex++; } else { - nextIndex++; key = nextIndex; - nextIndex++; } } - else if (settings.WordSeparators.Contains(ch)) + else if (WordBreakElements.Contains(sr.ContentElement.Name)) { nextIndex++; key = nextIndex; @@ -264,25 +289,15 @@ private static ComparisonUnit[] GetComparisonUnitList( { key = nextIndex; } - } - else if (WordBreakElements.Contains(sr.ContentElement.Name)) - { - nextIndex++; - key = nextIndex; - nextIndex++; - } - else - { - key = nextIndex; - } - return new Atgbw - { - Key = key, - ComparisonUnitAtomMember = sr, - NextIndex = nextIndex - }; - }) + return new Atgbw + { + Key = key, + ComparisonUnitAtomMember = sr, + NextIndex = nextIndex, + }; + } + ) .ToArray(); if (False) @@ -298,9 +313,7 @@ private static ComparisonUnit[] GetComparisonUnitList( TestUtil.NotePad(sbs); } - IEnumerable> groupedByWords = groupingKey - .GroupAdjacent(gc => gc.Key) - .ToArray(); + IEnumerable> groupedByWords = groupingKey.GroupAdjacent(gc => gc.Key).ToArray(); if (False) { @@ -320,22 +333,20 @@ private static ComparisonUnit[] GetComparisonUnitList( var withHierarchicalGroupingKey = groupedByWords .Select(g => + { + var hierarchicalGroupingArray = g.First() + .ComparisonUnitAtomMember.AncestorElements.Where(a => + ComparisonGroupingElements.Contains(a.Name) + ) + .Select(a => a.Name.LocalName + ":" + (string)a.Attribute(PtOpenXml.Unid)) + .ToArray(); + + return new WithHierarchicalGroupingKey { - var hierarchicalGroupingArray = g - .First() - .ComparisonUnitAtomMember - .AncestorElements - .Where(a => ComparisonGroupingElements.Contains(a.Name)) - .Select(a => a.Name.LocalName + ":" + (string) a.Attribute(PtOpenXml.Unid)) - .ToArray(); - - return new WithHierarchicalGroupingKey - { - ComparisonUnitWord = new ComparisonUnitWord(g.Select(gc => gc.ComparisonUnitAtomMember)), - HierarchicalGroupingArray = hierarchicalGroupingArray - }; - } - ) + ComparisonUnitWord = new ComparisonUnitWord(g.Select(gc => gc.ComparisonUnitAtomMember)), + HierarchicalGroupingArray = hierarchicalGroupingArray, + }; + }) .ToArray(); if (False) @@ -343,9 +354,11 @@ private static ComparisonUnit[] GetComparisonUnitList( var sb = new StringBuilder(); foreach (var group in withHierarchicalGroupingKey) { - sb.Append("Grouping Array: " + - @group.HierarchicalGroupingArray.Select(gam => gam + " - ").StringConcatenate() + - Environment.NewLine); + sb.Append( + "Grouping Array: " + + @group.HierarchicalGroupingArray.Select(gam => gam + " - ").StringConcatenate() + + Environment.NewLine + ); foreach (var gc in @group.ComparisonUnitWord.Contents) { sb.Append(" " + gc.ToString(0) + Environment.NewLine); @@ -369,18 +382,19 @@ private static ComparisonUnit[] GetComparisonUnitList( private static IEnumerable GetHierarchicalComparisonUnits( IEnumerable input, - int level) + int level + ) { - var grouped = input - .GroupAdjacent( - whgk => level >= whgk.HierarchicalGroupingArray.Length ? "" : whgk.HierarchicalGroupingArray[level]); + var grouped = input.GroupAdjacent(whgk => + level >= whgk.HierarchicalGroupingArray.Length ? "" : whgk.HierarchicalGroupingArray[level] + ); var retList = grouped .Select(gc => { if (gc.Key == "") { - return (IEnumerable) gc.Select(whgk => whgk.ComparisonUnitWord).ToList(); + return (IEnumerable)gc.Select(whgk => whgk.ComparisonUnitWord).ToList(); } var spl = gc.Key.Split(':'); diff --git a/Clippit/Comparer/WmlComparer.Private.Fields.cs b/Clippit/Comparer/WmlComparer.Private.Fields.cs index 8294e9a0..458d1441 100644 --- a/Clippit/Comparer/WmlComparer.Private.Fields.cs +++ b/Clippit/Comparer/WmlComparer.Private.Fields.cs @@ -13,261 +13,159 @@ public static partial class WmlComparer private static string NewLine => Environment.NewLine; - private static XAttribute[] NamespaceAttributes => new XAttribute[] - { - new(XNamespace.Xmlns + "wpc", WPC.wpc), - new(XNamespace.Xmlns + "mc", MC.mc), - new(XNamespace.Xmlns + "o", O.o), - new(XNamespace.Xmlns + "r", R.r), - new(XNamespace.Xmlns + "m", M.m), - new(XNamespace.Xmlns + "v", VML.vml), - new(XNamespace.Xmlns + "wp14", WP14.wp14), - new(XNamespace.Xmlns + "wp", WP.wp), - new(XNamespace.Xmlns + "w10", W10.w10), - new(XNamespace.Xmlns + "w", W.w), - new(XNamespace.Xmlns + "w14", W14.w14), - new(XNamespace.Xmlns + "wpg", WPG.wpg), - new(XNamespace.Xmlns + "wpi", WPI.wpi), - new(XNamespace.Xmlns + "wne", WNE.wne), - new(XNamespace.Xmlns + "wps", WPS.wps), - new(MC.Ignorable, "w14 wp14") - }; + private static XAttribute[] NamespaceAttributes => + new XAttribute[] + { + new(XNamespace.Xmlns + "wpc", WPC.wpc), + new(XNamespace.Xmlns + "mc", MC.mc), + new(XNamespace.Xmlns + "o", O.o), + new(XNamespace.Xmlns + "r", R.r), + new(XNamespace.Xmlns + "m", M.m), + new(XNamespace.Xmlns + "v", VML.vml), + new(XNamespace.Xmlns + "wp14", WP14.wp14), + new(XNamespace.Xmlns + "wp", WP.wp), + new(XNamespace.Xmlns + "w10", W10.w10), + new(XNamespace.Xmlns + "w", W.w), + new(XNamespace.Xmlns + "w14", W14.w14), + new(XNamespace.Xmlns + "wpg", WPG.wpg), + new(XNamespace.Xmlns + "wpi", WPI.wpi), + new(XNamespace.Xmlns + "wne", WNE.wne), + new(XNamespace.Xmlns + "wps", WPS.wps), + new(MC.Ignorable, "w14 wp14"), + }; - private static XName[] RevElementsWithNoText => new[] - { - M.oMath, - M.oMathPara, - W.drawing - }; + private static XName[] RevElementsWithNoText => new[] { M.oMath, M.oMathPara, W.drawing }; - private static XName[] AttributesToTrimWhenCloning => new[] - { - WP14.anchorId, - WP14.editId, - "ObjectID", - "ShapeID", - "id", - "type" - }; + private static XName[] AttributesToTrimWhenCloning => + new[] { WP14.anchorId, WP14.editId, "ObjectID", "ShapeID", "id", "type" }; private static int s_maxId; - private static XName[] WordBreakElements => new[] - { - W.pPr, - W.tab, - W.br, - W.continuationSeparator, - W.cr, - W.dayLong, - W.dayShort, - W.drawing, - W.pict, - W.endnoteRef, - W.footnoteRef, - W.monthLong, - W.monthShort, - W.noBreakHyphen, - W._object, - W.ptab, - W.separator, - W.sym, - W.yearLong, - W.yearShort, - M.oMathPara, - M.oMath, - W.footnoteReference, - W.endnoteReference - }; + private static XName[] WordBreakElements => + new[] + { + W.pPr, + W.tab, + W.br, + W.continuationSeparator, + W.cr, + W.dayLong, + W.dayShort, + W.drawing, + W.pict, + W.endnoteRef, + W.footnoteRef, + W.monthLong, + W.monthShort, + W.noBreakHyphen, + W._object, + W.ptab, + W.separator, + W.sym, + W.yearLong, + W.yearShort, + M.oMathPara, + M.oMath, + W.footnoteReference, + W.endnoteReference, + }; - private static XName[] AllowableRunChildren => new[] - { - W.br, - W.drawing, - W.cr, - W.dayLong, - W.dayShort, - W.footnoteReference, - W.endnoteReference, - W.monthLong, - W.monthShort, - W.noBreakHyphen, + private static XName[] AllowableRunChildren => + new[] + { + W.br, + W.drawing, + W.cr, + W.dayLong, + W.dayShort, + W.footnoteReference, + W.endnoteReference, + W.monthLong, + W.monthShort, + W.noBreakHyphen, + //W._object, + W.pgNum, + W.ptab, + W.softHyphen, + W.sym, + W.tab, + W.yearLong, + W.yearShort, + M.oMathPara, + M.oMath, + W.fldChar, + W.instrText, + }; - //W._object, - W.pgNum, - W.ptab, - W.softHyphen, - W.sym, - W.tab, - W.yearLong, - W.yearShort, - M.oMathPara, - M.oMath, - W.fldChar, - W.instrText - }; + private static XName[] ElementsToThrowAway => + new[] + { + W.bookmarkStart, + W.bookmarkEnd, + W.commentRangeStart, + W.commentRangeEnd, + W.lastRenderedPageBreak, + W.proofErr, + W.tblPr, + W.sectPr, + W.permEnd, + W.permStart, + W.footnoteRef, + W.endnoteRef, + W.separator, + W.continuationSeparator, + }; - private static XName[] ElementsToThrowAway => new[] - { - W.bookmarkStart, - W.bookmarkEnd, - W.commentRangeStart, - W.commentRangeEnd, - W.lastRenderedPageBreak, - W.proofErr, - W.tblPr, - W.sectPr, - W.permEnd, - W.permStart, - W.footnoteRef, - W.endnoteRef, - W.separator, - W.continuationSeparator - }; + private static XName[] ElementsToHaveSha1Hash => + new[] { W.p, W.tbl, W.tr, W.tc, W.drawing, W.pict, W.txbxContent }; - private static XName[] ElementsToHaveSha1Hash => new[] - { - W.p, - W.tbl, - W.tr, - W.tc, - W.drawing, - W.pict, - W.txbxContent - }; + private static XName[] InvalidElements => + new[] + { + W.altChunk, + W.customXml, + W.customXmlDelRangeEnd, + W.customXmlDelRangeStart, + W.customXmlInsRangeEnd, + W.customXmlInsRangeStart, + W.customXmlMoveFromRangeEnd, + W.customXmlMoveFromRangeStart, + W.customXmlMoveToRangeEnd, + W.customXmlMoveToRangeStart, + W.moveFrom, + W.moveFromRangeStart, + W.moveFromRangeEnd, + W.moveTo, + W.moveToRangeStart, + W.moveToRangeEnd, + W.subDoc, + }; - private static XName[] InvalidElements => new[] - { - W.altChunk, - W.customXml, - W.customXmlDelRangeEnd, - W.customXmlDelRangeStart, - W.customXmlInsRangeEnd, - W.customXmlInsRangeStart, - W.customXmlMoveFromRangeEnd, - W.customXmlMoveFromRangeStart, - W.customXmlMoveToRangeEnd, - W.customXmlMoveToRangeStart, - W.moveFrom, - W.moveFromRangeStart, - W.moveFromRangeEnd, - W.moveTo, - W.moveToRangeStart, - W.moveToRangeEnd, - W.subDoc - }; + private static RecursionInfo[] RecursionElements => + new RecursionInfo[] + { + new() { ElementName = W.del, ChildElementPropertyNames = null }, + new() { ElementName = W.ins, ChildElementPropertyNames = null }, + new() { ElementName = W.tbl, ChildElementPropertyNames = new[] { W.tblPr, W.tblGrid, W.tblPrEx } }, + new() { ElementName = W.tr, ChildElementPropertyNames = new[] { W.trPr, W.tblPrEx } }, + new() { ElementName = W.tc, ChildElementPropertyNames = new[] { W.tcPr, W.tblPrEx } }, + new() { ElementName = W.pict, ChildElementPropertyNames = new[] { VML.shapetype } }, + new() { ElementName = VML.group, ChildElementPropertyNames = null }, + new() { ElementName = VML.shape, ChildElementPropertyNames = null }, + new() { ElementName = VML.rect, ChildElementPropertyNames = null }, + new() { ElementName = VML.textbox, ChildElementPropertyNames = null }, + new() { ElementName = O._lock, ChildElementPropertyNames = null }, + new() { ElementName = W.txbxContent, ChildElementPropertyNames = null }, + new() { ElementName = W10.wrap, ChildElementPropertyNames = null }, + new() { ElementName = W.sdt, ChildElementPropertyNames = new[] { W.sdtPr, W.sdtEndPr } }, + new() { ElementName = W.sdtContent, ChildElementPropertyNames = null }, + new() { ElementName = W.hyperlink, ChildElementPropertyNames = null }, + new() { ElementName = W.fldSimple, ChildElementPropertyNames = null }, + new() { ElementName = VML.shapetype, ChildElementPropertyNames = null }, + new() { ElementName = W.smartTag, ChildElementPropertyNames = new[] { W.smartTagPr } }, + new() { ElementName = W.ruby, ChildElementPropertyNames = new[] { W.rubyPr } }, + }; - private static RecursionInfo[] RecursionElements => new RecursionInfo[] - { - new() - { - ElementName = W.del, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.ins, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.tbl, - ChildElementPropertyNames = new[] { W.tblPr, W.tblGrid, W.tblPrEx } - }, - new() - { - ElementName = W.tr, - ChildElementPropertyNames = new[] { W.trPr, W.tblPrEx } - }, - new() - { - ElementName = W.tc, - ChildElementPropertyNames = new[] { W.tcPr, W.tblPrEx } - }, - new() - { - ElementName = W.pict, - ChildElementPropertyNames = new[] { VML.shapetype } - }, - new() - { - ElementName = VML.group, - ChildElementPropertyNames = null - }, - new() - { - ElementName = VML.shape, - ChildElementPropertyNames = null - }, - new() - { - ElementName = VML.rect, - ChildElementPropertyNames = null - }, - new() - { - ElementName = VML.textbox, - ChildElementPropertyNames = null - }, - new() - { - ElementName = O._lock, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.txbxContent, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W10.wrap, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.sdt, - ChildElementPropertyNames = new[] { W.sdtPr, W.sdtEndPr } - }, - new() - { - ElementName = W.sdtContent, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.hyperlink, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.fldSimple, - ChildElementPropertyNames = null - }, - new() - { - ElementName = VML.shapetype, - ChildElementPropertyNames = null - }, - new() - { - ElementName = W.smartTag, - ChildElementPropertyNames = new[] { W.smartTagPr } - }, - new() - { - ElementName = W.ruby, - ChildElementPropertyNames = new[] { W.rubyPr } - } - }; - - private static XName[] ComparisonGroupingElements => new[] - { - W.p, - W.tbl, - W.tr, - W.tc, - W.txbxContent - }; + private static XName[] ComparisonGroupingElements => new[] { W.p, W.tbl, W.tr, W.tc, W.txbxContent }; } } diff --git a/Clippit/Comparer/WmlComparer.Private.Methods.Hashing.cs b/Clippit/Comparer/WmlComparer.Private.Methods.Hashing.cs index c7ece901..b5531bf0 100644 --- a/Clippit/Comparer/WmlComparer.Private.Methods.Hashing.cs +++ b/Clippit/Comparer/WmlComparer.Private.Methods.Hashing.cs @@ -15,7 +15,8 @@ public static partial class WmlComparer private static WmlDocument HashBlockLevelContent( WmlDocument source, WmlDocument sourceAfterProc, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { using var msSource = new MemoryStream(); using var msAfterProc = new MemoryStream(); @@ -31,7 +32,7 @@ private static WmlDocument HashBlockLevelContent( var sourceUnidDict = sourceMainRoot .Descendants() .Where(d => d.Name == W.p || d.Name == W.tbl || d.Name == W.tr) - .ToDictionary(d => (string) d.Attribute(PtOpenXml.Unid)); + .ToDictionary(d => (string)d.Attribute(PtOpenXml.Unid)); var afterProcMainXDoc = wDocAfterProc.MainDocumentPart.GetXDocument(); var afterProcMainRoot = afterProcMainXDoc.Root ?? throw new ArgumentException(); @@ -41,18 +42,19 @@ private static WmlDocument HashBlockLevelContent( foreach (var blockLevelContent in blockLevelElements) { - var cloneBlockLevelContentForHashing = (XElement) CloneBlockLevelContentForHashing( + var cloneBlockLevelContentForHashing = (XElement)CloneBlockLevelContentForHashing( wDocAfterProc.MainDocumentPart, blockLevelContent, true, - settings); + settings + ); var shaString = cloneBlockLevelContentForHashing .ToString(SaveOptions.DisableFormatting) .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", ""); var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString); - var thisUnid = (string) blockLevelContent.Attribute(PtOpenXml.Unid); + var thisUnid = (string)blockLevelContent.Attribute(PtOpenXml.Unid); if (thisUnid != null) { if (sourceUnidDict.ContainsKey(thisUnid)) @@ -80,40 +82,51 @@ private static object CloneBlockLevelContentForHashing( OpenXmlPart mainDocumentPart, XNode node, bool includeRelatedParts, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { if (node is XElement element) { - if (element.Name == W.bookmarkStart || - element.Name == W.bookmarkEnd || - element.Name == W.pPr || - element.Name == W.rPr) + if ( + element.Name == W.bookmarkStart + || element.Name == W.bookmarkEnd + || element.Name == W.pPr + || element.Name == W.rPr + ) { return null; } if (element.Name == W.p) { - var clonedPara = new XElement(element.Name, - element.Attributes().Where(a => a.Name != W.rsid && - a.Name != W.rsidDel && - a.Name != W.rsidP && - a.Name != W.rsidR && - a.Name != W.rsidRDefault && - a.Name != W.rsidRPr && - a.Name != W.rsidSect && - a.Name != W.rsidTr && - a.Name.Namespace != PtOpenXml.pt), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedPara = new XElement( + element.Name, + element + .Attributes() + .Where(a => + a.Name != W.rsid + && a.Name != W.rsidDel + && a.Name != W.rsidP + && a.Name != W.rsidR + && a.Name != W.rsidRDefault + && a.Name != W.rsidRPr + && a.Name != W.rsidSect + && a.Name != W.rsidTr + && a.Name.Namespace != PtOpenXml.pt + ), + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); var groupedRuns = clonedPara .Elements() - .GroupAdjacent(e => e.Name == W.r && - e.Elements().Count() == 1 && - e.Element(W.t) != null); + .GroupAdjacent(e => e.Name == W.r && e.Elements().Count() == 1 && e.Element(W.t) != null); - var clonedParaWithGroupedRuns = new XElement(element.Name, + var clonedParaWithGroupedRuns = new XElement( + element.Name, groupedRuns.Select(g => { if (g.Key) @@ -121,14 +134,13 @@ private static object CloneBlockLevelContentForHashing( var text = g.Select(t => t.Value).StringConcatenate(); if (settings.CaseInsensitive) text = text.ToUpper(settings.CultureInfo); - var newRun = (object) new XElement(W.r, - new XElement(W.t, - text)); + var newRun = (object)new XElement(W.r, new XElement(W.t, text)); return newRun; } return g; - })); + }) + ); return clonedParaWithGroupedRuns; } @@ -138,55 +150,84 @@ private static object CloneBlockLevelContentForHashing( var clonedRuns = element .Elements() .Where(e => e.Name != W.rPr) - .Select(rc => new XElement(W.r, - CloneBlockLevelContentForHashing(mainDocumentPart, rc, includeRelatedParts, settings))); + .Select(rc => new XElement( + W.r, + CloneBlockLevelContentForHashing(mainDocumentPart, rc, includeRelatedParts, settings) + )); return clonedRuns; } if (element.Name == W.tbl) { - var clonedTable = new XElement(W.tbl, - element.Elements(W.tr).Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedTable = new XElement( + W.tbl, + element + .Elements(W.tr) + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return clonedTable; } if (element.Name == W.tr) { - var clonedRow = new XElement(W.tr, - element.Elements(W.tc).Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedRow = new XElement( + W.tr, + element + .Elements(W.tc) + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return clonedRow; } if (element.Name == W.tc) { - var clonedCell = new XElement(W.tc, - element.Elements().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedCell = new XElement( + W.tc, + element + .Elements() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return clonedCell; } if (element.Name == W.tcPr) { - var clonedCellProps = new XElement(W.tcPr, - element.Elements(W.gridSpan).Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedCellProps = new XElement( + W.tcPr, + element + .Elements(W.gridSpan) + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return clonedCellProps; } if (element.Name == W.gridSpan) { - var clonedGridSpan = new XElement(W.gridSpan, - new XAttribute("val", (string) element.Attribute(W.val))); + var clonedGridSpan = new XElement( + W.gridSpan, + new XAttribute("val", (string)element.Attribute(W.val)) + ); return clonedGridSpan; } if (element.Name == W.txbxContent) { - var clonedTextbox = new XElement(W.txbxContent, - element.Elements().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var clonedTextbox = new XElement( + W.txbxContent, + element + .Elements() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return clonedTextbox; } @@ -194,8 +235,10 @@ private static object CloneBlockLevelContentForHashing( { if (ComparisonUnitWord.ElementsWithRelationshipIds.Contains(element.Name)) { - var newElement = new XElement(element.Name, - element.Attributes() + var newElement = new XElement( + element.Name, + element + .Attributes() .Where(a => a.Name.Namespace != PtOpenXml.pt) .Where(a => !AttributesToTrimWhenCloning.Contains(a.Name)) .Select(a => @@ -203,7 +246,7 @@ private static object CloneBlockLevelContentForHashing( if (!ComparisonUnitWord.RelationshipAttributeNames.Contains(a.Name)) return a; - var rId = (string) a; + var rId = (string)a; // could be an hyperlink relationship try @@ -222,7 +265,7 @@ private static object CloneBlockLevelContentForHashing( byte[] ba; using (var br = new BinaryReader(str)) { - ba = br.ReadBytes((int) str.Length); + ba = br.ReadBytes((int)str.Length); } var sha1 = WmlComparerUtil.SHA1HashStringForByteArray(ba); @@ -232,8 +275,9 @@ private static object CloneBlockLevelContentForHashing( } catch (ArgumentOutOfRangeException) { - var hr = - mainDocumentPart.HyperlinkRelationships.FirstOrDefault(z => z.Id == rId); + var hr = mainDocumentPart.HyperlinkRelationships.FirstOrDefault(z => + z.Id == rId + ); if (hr != null) { var str = hr.Uri.ToString(); @@ -241,8 +285,9 @@ private static object CloneBlockLevelContentForHashing( } // could be an external relationship - var er = - mainDocumentPart.ExternalRelationships.FirstOrDefault(z => z.Id == rId); + var er = mainDocumentPart.ExternalRelationships.FirstOrDefault(z => + z.Id == rId + ); if (er != null) { var str = er.Uri.ToString(); @@ -254,58 +299,88 @@ private static object CloneBlockLevelContentForHashing( return null; }), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return newElement; } } if (element.Name == VML.shape) { - return new XElement(element.Name, - element.Attributes() + return new XElement( + element.Name, + element + .Attributes() .Where(a => a.Name.Namespace != PtOpenXml.pt) .Where(a => a.Name != "style" && a.Name != "id" && a.Name != "type"), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); } if (element.Name == O.OLEObject) { - var o = new XElement(element.Name, - element.Attributes() + var o = new XElement( + element.Name, + element + .Attributes() .Where(a => a.Name.Namespace != PtOpenXml.pt) .Where(a => a.Name != "ObjectID" && a.Name != R.id), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return o; } if (element.Name == W._object) { - var o = new XElement(element.Name, - element.Attributes() - .Where(a => a.Name.Namespace != PtOpenXml.pt), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + var o = new XElement( + element.Name, + element.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt), + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); return o; } if (element.Name == WP.docPr) { - return new XElement(element.Name, - element.Attributes() - .Where(a => a.Name.Namespace != PtOpenXml.pt && a.Name != "id"), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + return new XElement( + element.Name, + element.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt && a.Name != "id"), + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); } - return new XElement(element.Name, - element.Attributes() + return new XElement( + element.Name, + element + .Attributes() .Where(a => a.Name.Namespace != PtOpenXml.pt) .Where(a => !AttributesToTrimWhenCloning.Contains(a.Name)), - element.Nodes().Select(n => - CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings))); + element + .Nodes() + .Select(n => + CloneBlockLevelContentForHashing(mainDocumentPart, n, includeRelatedParts, settings) + ) + ); } if (settings.CaseInsensitive) diff --git a/Clippit/Comparer/WmlComparer.Private.Methods.Lcs.cs b/Clippit/Comparer/WmlComparer.Private.Methods.Lcs.cs index dc7448be..08b414cc 100644 --- a/Clippit/Comparer/WmlComparer.Private.Methods.Lcs.cs +++ b/Clippit/Comparer/WmlComparer.Private.Methods.Lcs.cs @@ -25,7 +25,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = cul1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); return newListOfCorrelatedSequence; @@ -37,7 +37,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = cul2 + ComparisonUnitArray2 = cul2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); return newListOfCorrelatedSequence; @@ -177,10 +177,10 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow .Any(cs => { var otherThanText = cs.DescendantContentAtoms().Any(dca => dca.ContentElement.Name != W.t); - if (otherThanText) return true; + if (otherThanText) + return true; - var otherThanWordSplit = cs - .DescendantContentAtoms() + var otherThanWordSplit = cs.DescendantContentAtoms() .Any(dca => { var charValue = dca.ContentElement.Value; @@ -209,7 +209,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow if (!anyButWord1 && !anyButWord2) { var maxLen = Math.Max(cul1.Length, cul2.Length); - if (currentLongestCommonSequenceLength / (double) maxLen < settings.DetailThreshold) + if (currentLongestCommonSequenceLength / (double)maxLen < settings.DetailThreshold) { currentI1 = -1; currentI2 = -1; @@ -223,56 +223,42 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var leftLength = unknown.ComparisonUnitArray1.Length; var leftTables = unknown - .ComparisonUnitArray1 - .OfType() + .ComparisonUnitArray1.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Table); var leftRows = unknown - .ComparisonUnitArray1 - .OfType() + .ComparisonUnitArray1.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Row); var leftParagraphs = unknown - .ComparisonUnitArray1 - .OfType() + .ComparisonUnitArray1.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Paragraph); var leftTextboxes = unknown - .ComparisonUnitArray1 - .OfType() + .ComparisonUnitArray1.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Textbox); - var leftWords = unknown - .ComparisonUnitArray1 - .OfType() - .Count(); + var leftWords = unknown.ComparisonUnitArray1.OfType().Count(); var rightLength = unknown.ComparisonUnitArray2.Length; var rightTables = unknown - .ComparisonUnitArray2 - .OfType() + .ComparisonUnitArray2.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Table); var rightRows = unknown - .ComparisonUnitArray2 - .OfType() + .ComparisonUnitArray2.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Row); var rightParagraphs = unknown - .ComparisonUnitArray2 - .OfType() + .ComparisonUnitArray2.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Paragraph); var rightTextboxes = unknown - .ComparisonUnitArray2 - .OfType() + .ComparisonUnitArray2.OfType() .Count(l => l.ComparisonUnitGroupType == ComparisonUnitGroupType.Textbox); - var rightWords = unknown - .ComparisonUnitArray2 - .OfType() - .Count(); + var rightWords = unknown.ComparisonUnitArray2.OfType().Count(); // if either side has both words, rows and text boxes, then we need to separate out into separate // unknown correlated sequences @@ -288,14 +274,15 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var leftOnlyWordsRowsTextboxes = leftLength == leftWords + leftRows + leftTextboxes; var rightOnlyWordsRowsTextboxes = rightLength == rightWords + rightRows + rightTextboxes; - if ((leftWords > 0 || rightWords > 0) && - (leftRows > 0 || rightRows > 0 || leftTextboxes > 0 || rightTextboxes > 0) && - leftOnlyWordsRowsTextboxes && - rightOnlyWordsRowsTextboxes) + if ( + (leftWords > 0 || rightWords > 0) + && (leftRows > 0 || rightRows > 0 || leftTextboxes > 0 || rightTextboxes > 0) + && leftOnlyWordsRowsTextboxes + && rightOnlyWordsRowsTextboxes + ) { var leftGrouped = unknown - .ComparisonUnitArray1 - .GroupAdjacent(cu => + .ComparisonUnitArray1.GroupAdjacent(cu => { if (cu is ComparisonUnitWord) { @@ -318,8 +305,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow .ToArray(); var rightGrouped = unknown - .ComparisonUnitArray2 - .GroupAdjacent(cu => + .ComparisonUnitArray2.GroupAdjacent(cu => { if (cu is ComparisonUnitWord) { @@ -358,71 +344,71 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = leftGrouped[iLeft].ToArray(), ComparisonUnitArray2 = rightGrouped[iRight].ToArray(), - CorrelationStatus = CorrelationStatus.Unknown + CorrelationStatus = CorrelationStatus.Unknown, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); ++iLeft; ++iRight; } - // have to decide which of the following two branches to do first based on whether the left contains a paragraph mark // i.e. cant insert a string of deleted text right before a table. - else if (leftGrouped[iLeft].Key == "Word" && - leftGrouped[iLeft] - .Select(lg => lg.DescendantContentAtoms()) - .SelectMany(m => m).Last() - .ContentElement - .Name != W.pPr && - rightGrouped[iRight].Key == "Row") + else if ( + leftGrouped[iLeft].Key == "Word" + && leftGrouped[iLeft] + .Select(lg => lg.DescendantContentAtoms()) + .SelectMany(m => m) + .Last() + .ContentElement.Name != W.pPr + && rightGrouped[iRight].Key == "Row" + ) { var insertedCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = null, ComparisonUnitArray2 = rightGrouped[iRight].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); ++iRight; } - else if (rightGrouped[iRight].Key == "Word" && - rightGrouped[iRight] - .Select(lg => lg.DescendantContentAtoms()) - .SelectMany(m => m) - .Last() - .ContentElement - .Name != W.pPr && - leftGrouped[iLeft].Key == "Row") + else if ( + rightGrouped[iRight].Key == "Word" + && rightGrouped[iRight] + .Select(lg => lg.DescendantContentAtoms()) + .SelectMany(m => m) + .Last() + .ContentElement.Name != W.pPr + && leftGrouped[iLeft].Key == "Row" + ) { var insertedCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = null, ComparisonUnitArray2 = leftGrouped[iLeft].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); ++iLeft; } - else if (leftGrouped[iLeft].Key == "Word" && rightGrouped[iRight].Key != "Word") { var deletedCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = leftGrouped[iLeft].ToArray(), ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted + CorrelationStatus = CorrelationStatus.Deleted, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); ++iLeft; } - else if (leftGrouped[iLeft].Key != "Word" && rightGrouped[iRight].Key == "Word") { var insertedCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = null, ComparisonUnitArray2 = rightGrouped[iRight].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); ++iRight; @@ -440,7 +426,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = leftGrouped[j].ToArray(), ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted + CorrelationStatus = CorrelationStatus.Deleted, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -458,7 +444,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = null, ComparisonUnitArray2 = rightGrouped[j].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -471,24 +457,26 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow } // if both sides contain tables and paragraphs, then split into multiple unknown corr sequ - if (leftTables > 0 && rightTables > 0 && - leftParagraphs > 0 && rightParagraphs > 0 && - (leftLength > 1 || rightLength > 1)) + if ( + leftTables > 0 + && rightTables > 0 + && leftParagraphs > 0 + && rightParagraphs > 0 + && (leftLength > 1 || rightLength > 1) + ) { var leftGrouped = unknown - .ComparisonUnitArray1 - .GroupAdjacent(cu => + .ComparisonUnitArray1.GroupAdjacent(cu => { - var cug = (ComparisonUnitGroup) cu; + var cug = (ComparisonUnitGroup)cu; return cug.ComparisonUnitGroupType == ComparisonUnitGroupType.Table ? "Table" : "Para"; }) .ToArray(); var rightGrouped = unknown - .ComparisonUnitArray2 - .GroupAdjacent(cu => + .ComparisonUnitArray2.GroupAdjacent(cu => { - var cug = (ComparisonUnitGroup) cu; + var cug = (ComparisonUnitGroup)cu; return cug.ComparisonUnitGroupType == ComparisonUnitGroupType.Table ? "Table" : "Para"; }) .ToArray(); @@ -504,14 +492,16 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow while (true) { - if (leftGrouped[iLeft].Key == "Table" && rightGrouped[iRight].Key == "Table" || - leftGrouped[iLeft].Key == "Para" && rightGrouped[iRight].Key == "Para") + if ( + leftGrouped[iLeft].Key == "Table" && rightGrouped[iRight].Key == "Table" + || leftGrouped[iLeft].Key == "Para" && rightGrouped[iRight].Key == "Para" + ) { var unknownCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = leftGrouped[iLeft].ToArray(), ComparisonUnitArray2 = rightGrouped[iRight].ToArray(), - CorrelationStatus = CorrelationStatus.Unknown + CorrelationStatus = CorrelationStatus.Unknown, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); ++iLeft; @@ -523,7 +513,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = leftGrouped[iLeft].ToArray(), ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted + CorrelationStatus = CorrelationStatus.Deleted, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); ++iLeft; @@ -534,7 +524,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = null, ComparisonUnitArray2 = rightGrouped[iRight].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); ++iRight; @@ -552,7 +542,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = leftGrouped[j].ToArray(), ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted + CorrelationStatus = CorrelationStatus.Deleted, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -570,7 +560,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { ComparisonUnitArray1 = null, ComparisonUnitArray2 = rightGrouped[j].ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -583,8 +573,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow } // If both sides consists of a single table, and if the table contains merged cells, then mark as deleted/inserted - if (leftTables == 1 && leftLength == 1 && - rightTables == 1 && rightLength == 1) + if (leftTables == 1 && leftLength == 1 && rightTables == 1 && rightLength == 1) { var result = DoLcsAlgorithmForTable(unknown); if (result != null) @@ -597,23 +586,15 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow if (leftOnlyParasTablesTextboxes && rightOnlyParasTablesTextboxes) { // flatten paras and tables, and iterate - var left = unknown - .ComparisonUnitArray1 - .Select(cu => cu.Contents) - .SelectMany(m => m) - .ToArray(); + var left = unknown.ComparisonUnitArray1.Select(cu => cu.Contents).SelectMany(m => m).ToArray(); - var right = unknown - .ComparisonUnitArray2 - .Select(cu => cu.Contents) - .SelectMany(m => m) - .ToArray(); + var right = unknown.ComparisonUnitArray2.Select(cu => cu.Contents).SelectMany(m => m).ToArray(); var unknownCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = left, - ComparisonUnitArray2 = right + ComparisonUnitArray2 = right, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); @@ -623,11 +604,15 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow // if first of left is a row and first of right is a row // then flatten the row to cells and iterate. - if (unknown.ComparisonUnitArray1.FirstOrDefault() is ComparisonUnitGroup firstLeft && - unknown.ComparisonUnitArray2.FirstOrDefault() is ComparisonUnitGroup firstRight) + if ( + unknown.ComparisonUnitArray1.FirstOrDefault() is ComparisonUnitGroup firstLeft + && unknown.ComparisonUnitArray2.FirstOrDefault() is ComparisonUnitGroup firstRight + ) { - if (firstLeft.ComparisonUnitGroupType == ComparisonUnitGroupType.Row && - firstRight.ComparisonUnitGroupType == ComparisonUnitGroupType.Row) + if ( + firstLeft.ComparisonUnitGroupType == ComparisonUnitGroupType.Row + && firstRight.ComparisonUnitGroupType == ComparisonUnitGroupType.Row + ) { var leftContent = firstLeft.Contents.ToArray(); var rightContent = firstRight.Contents.ToArray(); @@ -648,38 +633,42 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow .ToArray(); } - var newCs = leftContent.Zip(rightContent, (l, r) => - { - if (l != null && r != null) + var newCs = leftContent + .Zip( + rightContent, + (l, r) => { - var unknownCorrelatedSequence = new CorrelatedSequence + if (l != null && r != null) { - ComparisonUnitArray1 = new[] { l }, - ComparisonUnitArray2 = new[] { r }, - CorrelationStatus = CorrelationStatus.Unknown - }; - return new[] { unknownCorrelatedSequence }; - } - - if (l == null) - { - var insertedCorrelatedSequence = new CorrelatedSequence + var unknownCorrelatedSequence = new CorrelatedSequence + { + ComparisonUnitArray1 = new[] { l }, + ComparisonUnitArray2 = new[] { r }, + CorrelationStatus = CorrelationStatus.Unknown, + }; + return new[] { unknownCorrelatedSequence }; + } + + if (l == null) { - ComparisonUnitArray1 = null, - ComparisonUnitArray2 = r.Contents.ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + var insertedCorrelatedSequence = new CorrelatedSequence + { + ComparisonUnitArray1 = null, + ComparisonUnitArray2 = r.Contents.ToArray(), + CorrelationStatus = CorrelationStatus.Inserted, + }; + return new[] { insertedCorrelatedSequence }; + } + + var deletedCorrelatedSequence = new CorrelatedSequence + { + ComparisonUnitArray1 = l.Contents.ToArray(), + ComparisonUnitArray2 = null, + CorrelationStatus = CorrelationStatus.Deleted, }; - return new[] { insertedCorrelatedSequence }; + return new[] { deletedCorrelatedSequence }; } - - var deletedCorrelatedSequence = new CorrelatedSequence - { - ComparisonUnitArray1 = l.Contents.ToArray(), - ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted - }; - return new[] { deletedCorrelatedSequence }; - }) + ) .SelectMany(m => m) .ToList(); @@ -688,15 +677,9 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow newListOfCorrelatedSequence.Add(cs); } - var remainderLeft = unknown - .ComparisonUnitArray1 - .Skip(1) - .ToArray(); + var remainderLeft = unknown.ComparisonUnitArray1.Skip(1).ToArray(); - var remainderRight = unknown - .ComparisonUnitArray2 - .Skip(1) - .ToArray(); + var remainderRight = unknown.ComparisonUnitArray2.Skip(1).ToArray(); if (remainderLeft.Length > 0 && remainderRight.Length == 0) { @@ -704,7 +687,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = remainderLeft, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -714,7 +697,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = remainderRight + ComparisonUnitArray2 = remainderRight, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -724,7 +707,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = remainderLeft, - ComparisonUnitArray2 = remainderRight + ComparisonUnitArray2 = remainderRight, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence2); } @@ -744,34 +727,26 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow return newListOfCorrelatedSequence; } - if (firstLeft.ComparisonUnitGroupType == ComparisonUnitGroupType.Cell && - firstRight.ComparisonUnitGroupType == ComparisonUnitGroupType.Cell) + if ( + firstLeft.ComparisonUnitGroupType == ComparisonUnitGroupType.Cell + && firstRight.ComparisonUnitGroupType == ComparisonUnitGroupType.Cell + ) { - var left = firstLeft - .Contents - .ToArray(); + var left = firstLeft.Contents.ToArray(); - var right = firstRight - .Contents - .ToArray(); + var right = firstRight.Contents.ToArray(); var unknownCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = left, - ComparisonUnitArray2 = right + ComparisonUnitArray2 = right, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); - var remainderLeft = unknown - .ComparisonUnitArray1 - .Skip(1) - .ToArray(); + var remainderLeft = unknown.ComparisonUnitArray1.Skip(1).ToArray(); - var remainderRight = unknown - .ComparisonUnitArray2 - .Skip(1) - .ToArray(); + var remainderRight = unknown.ComparisonUnitArray2.Skip(1).ToArray(); if (remainderLeft.Length > 0 && remainderRight.Length == 0) { @@ -779,7 +754,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = remainderLeft, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -789,7 +764,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = remainderRight + ComparisonUnitArray2 = remainderRight, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -799,7 +774,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = remainderLeft, - ComparisonUnitArray2 = remainderRight + ComparisonUnitArray2 = remainderRight, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence2); } @@ -810,15 +785,17 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow if (unknown.ComparisonUnitArray1.Any() && unknown.ComparisonUnitArray2.Any()) { - if (unknown.ComparisonUnitArray1.First() is ComparisonUnitWord && - unknown.ComparisonUnitArray2.First() is ComparisonUnitGroup right && - right.ComparisonUnitGroupType == ComparisonUnitGroupType.Row) + if ( + unknown.ComparisonUnitArray1.First() is ComparisonUnitWord + && unknown.ComparisonUnitArray2.First() is ComparisonUnitGroup right + && right.ComparisonUnitGroupType == ComparisonUnitGroupType.Row + ) { var insertedCorrelatedSequence3 = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 + ComparisonUnitArray2 = unknown.ComparisonUnitArray2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence3); @@ -826,22 +803,24 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence3); return newListOfCorrelatedSequence; } - if (unknown.ComparisonUnitArray2.First() is ComparisonUnitWord && - unknown.ComparisonUnitArray1.First() is ComparisonUnitGroup left2 && - left2.ComparisonUnitGroupType == ComparisonUnitGroupType.Row) + if ( + unknown.ComparisonUnitArray2.First() is ComparisonUnitWord + && unknown.ComparisonUnitArray1.First() is ComparisonUnitGroup left2 + && left2.ComparisonUnitGroupType == ComparisonUnitGroupType.Row + ) { var deletedCorrelatedSequence3 = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence3); @@ -849,7 +828,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 + ComparisonUnitArray2 = unknown.ComparisonUnitArray2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence3); @@ -857,25 +836,25 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow } var lastContentAtomLeft = unknown - .ComparisonUnitArray1 - .Select(cu => cu.DescendantContentAtoms().Last()) + .ComparisonUnitArray1.Select(cu => cu.DescendantContentAtoms().Last()) .LastOrDefault(); var lastContentAtomRight = unknown - .ComparisonUnitArray2 - .Select(cu => cu.DescendantContentAtoms().Last()) + .ComparisonUnitArray2.Select(cu => cu.DescendantContentAtoms().Last()) .LastOrDefault(); if (lastContentAtomLeft != null && lastContentAtomRight != null) { - if (lastContentAtomLeft.ContentElement.Name == W.pPr && - lastContentAtomRight.ContentElement.Name != W.pPr) + if ( + lastContentAtomLeft.ContentElement.Name == W.pPr + && lastContentAtomRight.ContentElement.Name != W.pPr + ) { var insertedCorrelatedSequence5 = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 + ComparisonUnitArray2 = unknown.ComparisonUnitArray2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence5); @@ -883,21 +862,23 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence5); return newListOfCorrelatedSequence; } - if (lastContentAtomLeft.ContentElement.Name != W.pPr && - lastContentAtomRight.ContentElement.Name == W.pPr) + if ( + lastContentAtomLeft.ContentElement.Name != W.pPr + && lastContentAtomRight.ContentElement.Name == W.pPr + ) { var deletedCorrelatedSequence5 = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence5); @@ -905,7 +886,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 + ComparisonUnitArray2 = unknown.ComparisonUnitArray2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence5); @@ -918,7 +899,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1, - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence4); @@ -926,7 +907,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 + ComparisonUnitArray2 = unknown.ComparisonUnitArray2, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence4); @@ -949,8 +930,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow if (currentLongestCommonSequenceLength != 0) { var commonSeq = unknown - .ComparisonUnitArray1 - .Skip(currentI1) + .ComparisonUnitArray1.Skip(currentI1) .Take(currentLongestCommonSequenceLength) .ToList(); @@ -958,26 +938,26 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow if (firstOfCommonSeq is ComparisonUnitWord) { // are there any paragraph marks in the common seq at end? - if (commonSeq.Any(cu => - { - var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); - if (firstComparisonUnitAtom == null) - return false; + if ( + commonSeq.Any(cu => + { + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); + if (firstComparisonUnitAtom == null) + return false; - return firstComparisonUnitAtom.ContentElement.Name == W.pPr; - })) + return firstComparisonUnitAtom.ContentElement.Name == W.pPr; + }) + ) { remainingInLeftParagraph = unknown - .ComparisonUnitArray1 - .Take(currentI1) + .ComparisonUnitArray1.Take(currentI1) .Reverse() .TakeWhile(cu => { if (cu is not ComparisonUnitWord) return false; - var firstComparisonUnitAtom = - cu.Contents.OfType().FirstOrDefault(); + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); if (firstComparisonUnitAtom == null) return true; @@ -985,16 +965,14 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow }) .Count(); remainingInRightParagraph = unknown - .ComparisonUnitArray2 - .Take(currentI2) + .ComparisonUnitArray2.Take(currentI2) .Reverse() .TakeWhile(cu => { if (cu is not ComparisonUnitWord) return false; - var firstComparisonUnitAtom = - cu.Contents.OfType().FirstOrDefault(); + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); if (firstComparisonUnitAtom == null) return true; @@ -1013,10 +991,8 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var deletedCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Deleted, - ComparisonUnitArray1 = cul1 - .Take(countBeforeCurrentParagraphLeft) - .ToArray(), - ComparisonUnitArray2 = null + ComparisonUnitArray1 = cul1.Take(countBeforeCurrentParagraphLeft).ToArray(), + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -1026,9 +1002,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = cul2 - .Take(countBeforeCurrentParagraphRight) - .ToArray() + ComparisonUnitArray2 = cul2.Take(countBeforeCurrentParagraphRight).ToArray(), }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -1037,12 +1011,8 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var unknownCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, - ComparisonUnitArray1 = cul1 - .Take(countBeforeCurrentParagraphLeft) - .ToArray(), - ComparisonUnitArray2 = cul2 - .Take(countBeforeCurrentParagraphRight) - .ToArray() + ComparisonUnitArray1 = cul1.Take(countBeforeCurrentParagraphLeft).ToArray(), + ComparisonUnitArray2 = cul2.Take(countBeforeCurrentParagraphRight).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); @@ -1057,11 +1027,10 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var deletedCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Deleted, - ComparisonUnitArray1 = cul1 - .Skip(countBeforeCurrentParagraphLeft) + ComparisonUnitArray1 = cul1.Skip(countBeforeCurrentParagraphLeft) .Take(remainingInLeftParagraph) .ToArray(), - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -1071,10 +1040,9 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = cul2 - .Skip(countBeforeCurrentParagraphRight) + ComparisonUnitArray2 = cul2.Skip(countBeforeCurrentParagraphRight) .Take(remainingInRightParagraph) - .ToArray() + .ToArray(), }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -1083,14 +1051,12 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var unknownCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, - ComparisonUnitArray1 = cul1 - .Skip(countBeforeCurrentParagraphLeft) + ComparisonUnitArray1 = cul1.Skip(countBeforeCurrentParagraphLeft) .Take(remainingInLeftParagraph) .ToArray(), - ComparisonUnitArray2 = cul2 - .Skip(countBeforeCurrentParagraphRight) + ComparisonUnitArray2 = cul2.Skip(countBeforeCurrentParagraphRight) .Take(remainingInRightParagraph) - .ToArray() + .ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); } @@ -1102,34 +1068,26 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow var middleEqual = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Equal, - ComparisonUnitArray1 = cul1 - .Skip(currentI1) - .Take(currentLongestCommonSequenceLength) - .ToArray(), - ComparisonUnitArray2 = cul2 - .Skip(currentI2) - .Take(currentLongestCommonSequenceLength) - .ToArray() + ComparisonUnitArray1 = cul1.Skip(currentI1).Take(currentLongestCommonSequenceLength).ToArray(), + ComparisonUnitArray2 = cul2.Skip(currentI2).Take(currentLongestCommonSequenceLength).ToArray(), }; newListOfCorrelatedSequence.Add(middleEqual); - var endI1 = currentI1 + currentLongestCommonSequenceLength; var endI2 = currentI2 + currentLongestCommonSequenceLength; - var remaining1 = cul1 - .Skip(endI1) - .ToArray(); + var remaining1 = cul1.Skip(endI1).ToArray(); - var remaining2 = cul2 - .Skip(endI2) - .ToArray(); + var remaining2 = cul2.Skip(endI2).ToArray(); // here is the point that we want to make a new unknown from this point to the end of the paragraph that // contains the equal parts. // this will never hurt anything, and will in many cases result in a better difference. - if (middleEqual.ComparisonUnitArray1[middleEqual.ComparisonUnitArray1.Length - 1] is ComparisonUnitWord leftCuw) + if ( + middleEqual.ComparisonUnitArray1[middleEqual.ComparisonUnitArray1.Length - 1] + is ComparisonUnitWord leftCuw + ) { var lastContentAtom = leftCuw.DescendantContentAtoms().LastOrDefault(); @@ -1143,7 +1101,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = remaining1.Take(idx1).ToArray(), - ComparisonUnitArray2 = remaining2.Take(idx2).ToArray() + ComparisonUnitArray2 = remaining2.Take(idx2).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequenceRemaining); @@ -1151,7 +1109,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = remaining1.Skip(idx1).ToArray(), - ComparisonUnitArray2 = remaining2.Skip(idx2).ToArray() + ComparisonUnitArray2 = remaining2.Skip(idx2).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequenceAfter); @@ -1163,7 +1121,7 @@ private static List DoLcsAlgorithm(CorrelatedSequence unknow { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = remaining1, - ComparisonUnitArray2 = remaining2 + ComparisonUnitArray2 = remaining2, }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence20); @@ -1180,20 +1138,16 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc // This is true regardless of whether there are horizontally or vertically merged cells, since that // characteristic is incorporated into the CorrespondingSHA1Hash. This is probably not very common, but it // will never do any harm. - var tblGroup1 = (ComparisonUnitGroup) unknown.ComparisonUnitArray1.First(); - var tblGroup2 = (ComparisonUnitGroup) unknown.ComparisonUnitArray2.First(); + var tblGroup1 = (ComparisonUnitGroup)unknown.ComparisonUnitArray1.First(); + var tblGroup2 = (ComparisonUnitGroup)unknown.ComparisonUnitArray2.First(); if (tblGroup1.Contents.Count == tblGroup2.Contents.Count) // if there are the same number of rows { var zipped = tblGroup1 - .Contents - .Zip( + .Contents.Zip( tblGroup2.Contents, - (r1, r2) => new - { - Row1 = r1 as ComparisonUnitGroup, - Row2 = r2 as ComparisonUnitGroup - }) + (r1, r2) => new { Row1 = r1 as ComparisonUnitGroup, Row2 = r2 as ComparisonUnitGroup } + ) .ToList(); var canCollapse = zipped.All(z => z.Row1.CorrelatedSHA1Hash == z.Row2.CorrelatedSHA1Hash); @@ -1207,7 +1161,7 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc { ComparisonUnitArray1 = new ComparisonUnit[] { z.Row1 }, ComparisonUnitArray2 = new ComparisonUnit[] { z.Row2 }, - CorrelationStatus = CorrelationStatus.Unknown + CorrelationStatus = CorrelationStatus.Unknown, }; return unknownCorrelatedSequence; }) @@ -1222,10 +1176,7 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc throw new OpenXmlPowerToolsException("Internal error"); } - var tblElement1 = firstContentAtom1 - .AncestorElements - .Reverse() - .First(a => a.Name == W.tbl); + var tblElement1 = firstContentAtom1.AncestorElements.Reverse().First(a => a.Name == W.tbl); var firstContentAtom2 = tblGroup2.DescendantContentAtoms().FirstOrDefault(); if (firstContentAtom2 == null) @@ -1233,32 +1184,26 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc throw new OpenXmlPowerToolsException("Internal error"); } - var tblElement2 = firstContentAtom2 - .AncestorElements - .Reverse() - .First(a => a.Name == W.tbl); + var tblElement2 = firstContentAtom2.AncestorElements.Reverse().First(a => a.Name == W.tbl); - var leftContainsMerged = tblElement1 - .Descendants() - .Any(d => d.Name == W.vMerge || d.Name == W.gridSpan); + var leftContainsMerged = tblElement1.Descendants().Any(d => d.Name == W.vMerge || d.Name == W.gridSpan); - var rightContainsMerged = tblElement2 - .Descendants() - .Any(d => d.Name == W.vMerge || d.Name == W.gridSpan); + var rightContainsMerged = tblElement2.Descendants().Any(d => d.Name == W.vMerge || d.Name == W.gridSpan); if (leftContainsMerged || rightContainsMerged) { // If StructureSha1Hash is the same for both tables, then we know that the structure of the tables is // identical, so we can break into correlated sequences for rows. - if (tblGroup1.StructureSHA1Hash != null && - tblGroup2.StructureSHA1Hash != null && - tblGroup1.StructureSHA1Hash == tblGroup2.StructureSHA1Hash) + if ( + tblGroup1.StructureSHA1Hash != null + && tblGroup2.StructureSHA1Hash != null + && tblGroup1.StructureSHA1Hash == tblGroup2.StructureSHA1Hash + ) { - var zipped = tblGroup1.Contents.Zip(tblGroup2.Contents, (r1, r2) => new - { - Row1 = r1 as ComparisonUnitGroup, - Row2 = r2 as ComparisonUnitGroup - }); + var zipped = tblGroup1.Contents.Zip( + tblGroup2.Contents, + (r1, r2) => new { Row1 = r1 as ComparisonUnitGroup, Row2 = r2 as ComparisonUnitGroup } + ); newListOfCorrelatedSequence = zipped .Select(z => { @@ -1266,7 +1211,7 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc { ComparisonUnitArray1 = new ComparisonUnit[] { z.Row1 }, ComparisonUnitArray2 = new ComparisonUnit[] { z.Row2 }, - CorrelationStatus = CorrelationStatus.Unknown + CorrelationStatus = CorrelationStatus.Unknown, }; return unknownCorrelatedSequence; }) @@ -1278,12 +1223,11 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc var deletedCorrelatedSequence = new CorrelatedSequence { ComparisonUnitArray1 = unknown - .ComparisonUnitArray1 - .Select(z => z.Contents) + .ComparisonUnitArray1.Select(z => z.Contents) .SelectMany(m => m) .ToArray(), ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted + CorrelationStatus = CorrelationStatus.Deleted, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); @@ -1292,11 +1236,10 @@ private static List DoLcsAlgorithmForTable(CorrelatedSequenc { ComparisonUnitArray1 = null, ComparisonUnitArray2 = unknown - .ComparisonUnitArray2 - .Select(z => z.Contents) + .ComparisonUnitArray2.Select(z => z.Contents) .SelectMany(m => m) .ToArray(), - CorrelationStatus = CorrelationStatus.Inserted + CorrelationStatus = CorrelationStatus.Inserted, }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); @@ -1311,7 +1254,7 @@ private static int FindIndexOfNextParaMark(ComparisonUnit[] cul) { for (var i = 0; i < cul.Length; i++) { - var cuw = (ComparisonUnitWord) cul[i]; + var cuw = (ComparisonUnitWord)cul[i]; var lastAtom = cuw.DescendantContentAtoms().LastOrDefault(); if (lastAtom?.ContentElement.Name == W.pPr) { diff --git a/Clippit/Comparer/WmlComparer.Private.Methods.PreProcessMarkup.cs b/Clippit/Comparer/WmlComparer.Private.Methods.PreProcessMarkup.cs index 7858fa87..7623830f 100644 --- a/Clippit/Comparer/WmlComparer.Private.Methods.PreProcessMarkup.cs +++ b/Clippit/Comparer/WmlComparer.Private.Methods.PreProcessMarkup.cs @@ -24,7 +24,8 @@ private static WmlDocument PreProcessMarkup(WmlDocument source, int startingIdFo { MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings( MarkupCompatibilityProcessMode.ProcessAllParts, - FileFormatVersions.Office2007) + FileFormatVersions.Office2007 + ), }; using (var wDoc = WordprocessingDocument.Open(ms, true, os)) @@ -54,7 +55,8 @@ private static WmlDocument PreProcessMarkup(WmlDocument source, int startingIdFo { MarkupCompatibilityProcessSettings = new MarkupCompatibilityProcessSettings( MarkupCompatibilityProcessMode.NoProcess, // Otherwise OpenXml delete custom `pt14:Unid` attributes on save - FileFormatVersions.Office2007) + FileFormatVersions.Office2007 + ), }; using (var wDoc = WordprocessingDocument.Open(ms, true, os)) @@ -82,7 +84,7 @@ private static WmlDocument PreProcessMarkup(WmlDocument source, int startingIdFo RemoveProof = true, RemoveSmartTags = true, RemoveSoftHyphens = true, - RemoveHyperlinks = true + RemoveHyperlinks = true, }; MarkupSimplifier.SimplifyMarkup(wDoc, msSettings); ChangeFootnoteEndnoteReferencesToUniqueRange(wDoc, startingIdForFootnotesEndnotes); @@ -111,10 +113,8 @@ private static void TestForInvalidContent(WordprocessingDocument wDoc) private static void RemoveExistingPowerToolsMarkup(WordprocessingDocument wDoc) { - wDoc.MainDocumentPart - .GetXDocument() - .Root? - .Descendants() + wDoc.MainDocumentPart.GetXDocument() + .Root?.Descendants() .Attributes() .Where(a => a.Name.Namespace == PtOpenXml.pt) .Where(a => a.Name != PtOpenXml.Unid) @@ -127,8 +127,7 @@ private static void RemoveExistingPowerToolsMarkup(WordprocessingDocument wDoc) { var fnXDoc = fnPart.GetXDocument(); fnXDoc - .Root? - .Descendants() + .Root?.Descendants() .Attributes() .Where(a => a.Name.Namespace == PtOpenXml.pt) .Where(a => a.Name != PtOpenXml.Unid) @@ -142,8 +141,7 @@ private static void RemoveExistingPowerToolsMarkup(WordprocessingDocument wDoc) { var enXDoc = enPart.GetXDocument(); enXDoc - .Root? - .Descendants() + .Root?.Descendants() .Attributes() .Where(a => a.Name.Namespace == PtOpenXml.pt) .Where(a => a.Name != PtOpenXml.Unid) @@ -155,14 +153,14 @@ private static void RemoveExistingPowerToolsMarkup(WordprocessingDocument wDoc) private static void ChangeFootnoteEndnoteReferencesToUniqueRange( WordprocessingDocument wDoc, - int startingIdForFootnotesEndnotes) + int startingIdForFootnotesEndnotes + ) { var mainDocPart = wDoc.MainDocumentPart; var footnotesPart = wDoc.MainDocumentPart.FootnotesPart; var endnotesPart = wDoc.MainDocumentPart.EndnotesPart; - var document = - mainDocPart.GetXDocument().Root ?? throw new OpenXmlPowerToolsException("Invalid document."); + var document = mainDocPart.GetXDocument().Root ?? throw new OpenXmlPowerToolsException("Invalid document."); var footnotes = footnotesPart?.GetXDocument().Root; var endnotes = endnotesPart?.GetXDocument().Root; @@ -173,15 +171,13 @@ private static void ChangeFootnoteEndnoteReferencesToUniqueRange( foreach (var r in references) { - var oldId = (string) r.Attribute(W.id); + var oldId = (string)r.Attribute(W.id); var newId = startingIdForFootnotesEndnotes.ToString(); startingIdForFootnotesEndnotes++; r.SetAttributeValue(W.id, newId); if (r.Name == W.footnoteReference) { - var fn = footnotes? - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + var fn = footnotes?.Elements().FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); if (fn == null) { @@ -192,9 +188,7 @@ private static void ChangeFootnoteEndnoteReferencesToUniqueRange( } else { - var en = endnotes? - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + var en = endnotes?.Elements().FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); if (en == null) { @@ -286,7 +280,8 @@ private static void FillInEmptyFootnotesEndnotes(WordprocessingDocument wDoc) -"); +" + ); var emptyEndnote = XElement.Parse( @" @@ -299,7 +294,8 @@ private static void FillInEmptyFootnotesEndnotes(WordprocessingDocument wDoc) -"); +" + ); var footnotePart = wDoc.MainDocumentPart.FootnotesPart; if (footnotePart != null) diff --git a/Clippit/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs b/Clippit/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs index b624a4d3..619ab26c 100644 --- a/Clippit/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs +++ b/Clippit/Comparer/WmlComparer.Private.Methods.ProduceDocument.cs @@ -19,15 +19,11 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( WmlComparerSettings settings, WmlDocument wmlResult, WordprocessingDocument wDoc1, - WordprocessingDocument wDoc2) + WordprocessingDocument wDoc2 + ) { // save away sectPr so that can set in the newly produced document. - var savedSectPr = wDoc1 - .MainDocumentPart - .GetXDocument() - .Root? - .Element(W.body)? - .Element(W.sectPr); + var savedSectPr = wDoc1.MainDocumentPart.GetXDocument().Root?.Element(W.body)?.Element(W.sectPr); var contentParent1 = wDoc1.MainDocumentPart.GetXDocument().Root?.Element(W.body); AddSha1HashToBlockLevelContent(wDoc1.MainDocumentPart, contentParent1, settings); @@ -38,7 +34,8 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( var cal1 = CreateComparisonUnitAtomList( wDoc1.MainDocumentPart, wDoc1.MainDocumentPart.GetXDocument().Root?.Element(W.body), - settings); + settings + ); if (False) { @@ -61,7 +58,8 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( var cal2 = CreateComparisonUnitAtomList( wDoc2.MainDocumentPart, wDoc2.MainDocumentPart.GetXDocument().Root?.Element(W.body), - settings); + settings + ); if (False) { @@ -154,8 +152,7 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( { var xDoc = wDocWithRevisions.MainDocumentPart.GetXDocument(); var rootNamespaceAttributes = xDoc - .Root? - .Attributes() + .Root?.Attributes() .Where(a => a.IsNamespaceDeclaration || a.Name.Namespace == MC.mc) .ToList(); @@ -164,30 +161,31 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( var newBodyChildren = ProduceNewWmlMarkupFromCorrelatedSequence( wDocWithRevisions.MainDocumentPart, listOfComparisonUnitAtoms, - settings); + settings + ); var newXDoc = new XDocument(); - newXDoc.Add( - new XElement(W.document, - rootNamespaceAttributes, - new XElement(W.body, newBodyChildren))); + newXDoc.Add(new XElement(W.document, rootNamespaceAttributes, new XElement(W.body, newBodyChildren))); MarkContentAsDeletedOrInserted(newXDoc, settings); CoalesceAdjacentRunsWithIdenticalFormatting(newXDoc); IgnorePt14Namespace(newXDoc.Root); - ProcessFootnoteEndnote(settings, + ProcessFootnoteEndnote( + settings, listOfComparisonUnitAtoms, wDoc1.MainDocumentPart, wDoc2.MainDocumentPart, - newXDoc); + newXDoc + ); RectifyFootnoteEndnoteIds( wDoc1.MainDocumentPart, wDoc2.MainDocumentPart, wDocWithRevisions.MainDocumentPart, newXDoc, - settings); + settings + ); ConjoinDeletedInsertedParagraphMarks(wDocWithRevisions.MainDocumentPart, newXDoc); @@ -195,7 +193,7 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( // little bit of cleanup MoveLastSectPrToChildOfBody(newXDoc); - var newXDoc2Root = (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(newXDoc.Root); + var newXDoc2Root = (XElement)WordprocessingMLUtil.WmlOrderElementsPerStandard(newXDoc.Root); xDoc.Root?.ReplaceWith(newXDoc2Root); /**********************************************************************************************/ @@ -212,13 +210,15 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( var xd = wDocWithRevisions.MainDocumentPart.GetXDocument(); // add everything but headers/footers - var clonedSectPr = new XElement(W.sectPr, + var clonedSectPr = new XElement( + W.sectPr, savedSectPr.Attributes(), savedSectPr.Element(W.type), savedSectPr.Element(W.pgSz), savedSectPr.Element(W.pgMar), savedSectPr.Element(W.cols), - savedSectPr.Element(W.titlePg)); + savedSectPr.Element(W.titlePg) + ); xd.Root?.Element(W.body)?.Add(clonedSectPr); } /**********************************************************************************************/ @@ -249,7 +249,11 @@ private static WmlDocument ProduceDocumentWithTrackedRevisions( return updatedWmlResult; } - private static void AddSha1HashToBlockLevelContent(OpenXmlPart part, XElement contentParent, WmlComparerSettings settings) + private static void AddSha1HashToBlockLevelContent( + OpenXmlPart part, + XElement contentParent, + WmlComparerSettings settings + ) { var blockLevelContentToAnnotate = contentParent .Descendants() @@ -257,24 +261,29 @@ private static void AddSha1HashToBlockLevelContent(OpenXmlPart part, XElement co foreach (var blockLevelContent in blockLevelContentToAnnotate) { - var cloneBlockLevelContentForHashing = - (XElement) CloneBlockLevelContentForHashing(part, blockLevelContent, true, settings); - var shaString = cloneBlockLevelContentForHashing.ToString(SaveOptions.DisableFormatting) + var cloneBlockLevelContentForHashing = (XElement)CloneBlockLevelContentForHashing( + part, + blockLevelContent, + true, + settings + ); + var shaString = cloneBlockLevelContentForHashing + .ToString(SaveOptions.DisableFormatting) .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", ""); var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString); blockLevelContent.Add(new XAttribute(PtOpenXml.SHA1Hash, sha1Hash)); - if (blockLevelContent.Name == W.tbl || - blockLevelContent.Name == W.tr) + if (blockLevelContent.Name == W.tbl || blockLevelContent.Name == W.tr) { - var clonedForStructureHash = (XElement) CloneForStructureHash(cloneBlockLevelContentForHashing); + var clonedForStructureHash = (XElement)CloneForStructureHash(cloneBlockLevelContentForHashing); // this is a convenient place to look at why tables are being compared as different. //if (blockLevelContent.Name == W.tbl) // Console.WriteLine(); - var shaString2 = clonedForStructureHash.ToString(SaveOptions.DisableFormatting) + var shaString2 = clonedForStructureHash + .ToString(SaveOptions.DisableFormatting) .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", ""); var sha1Hash2 = WmlComparerUtil.SHA1HashStringForUTF8String(shaString2); blockLevelContent.Add(new XAttribute(PtOpenXml.StructureSHA1Hash, sha1Hash2)); @@ -282,19 +291,20 @@ private static void AddSha1HashToBlockLevelContent(OpenXmlPart part, XElement co } } - private static List Lcs(ComparisonUnit[] cu1, ComparisonUnit[] cu2, WmlComparerSettings settings) + private static List Lcs( + ComparisonUnit[] cu1, + ComparisonUnit[] cu2, + WmlComparerSettings settings + ) { // set up initial state - one CorrelatedSequence, UnKnown, contents == entire sequences (both) var cs = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = cu1, - ComparisonUnitArray2 = cu2 - }; - var csList = new List - { - cs + ComparisonUnitArray2 = cu2, }; + var csList = new List { cs }; while (true) { @@ -307,8 +317,7 @@ private static List Lcs(ComparisonUnit[] cu1, ComparisonUnit TestUtil.NotePad(sbs); } - var unknown = csList - .FirstOrDefault(z => z.CorrelationStatus == CorrelationStatus.Unknown); + var unknown = csList.FirstOrDefault(z => z.CorrelationStatus == CorrelationStatus.Unknown); if (unknown != null) { @@ -351,10 +360,16 @@ private static List Lcs(ComparisonUnit[] cu1, ComparisonUnit } } - private static void MarkRowsAsDeletedOrInserted(WmlComparerSettings settings, List correlatedSequence) + private static void MarkRowsAsDeletedOrInserted( + WmlComparerSettings settings, + List correlatedSequence + ) { - foreach (var dcs in correlatedSequence.Where(cs => - cs.CorrelationStatus is CorrelationStatus.Deleted or CorrelationStatus.Inserted)) + foreach ( + var dcs in correlatedSequence.Where(cs => + cs.CorrelationStatus is CorrelationStatus.Deleted or CorrelationStatus.Inserted + ) + ) { // iterate through all deleted/inserted items in dcs.ComparisonUnitArray1/ComparisonUnitArray2 var toIterateThrough = dcs.ComparisonUnitArray1; @@ -375,10 +390,7 @@ private static void MarkRowsAsDeletedOrInserted(WmlComparerSettings settings, Li if (firstContentAtom == null) throw new OpenXmlPowerToolsException("Internal error"); - var tr = firstContentAtom - .AncestorElements - .Reverse() - .FirstOrDefault(a => a.Name == W.tr); + var tr = firstContentAtom.AncestorElements.Reverse().FirstOrDefault(a => a.Name == W.tr); if (tr == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -394,12 +406,16 @@ private static void MarkRowsAsDeletedOrInserted(WmlComparerSettings settings, Li { CorrelationStatus.Deleted => W.del, CorrelationStatus.Inserted => W.ins, - _ => null + _ => null, }; - trPr.Add(new XElement(revTrackElementName, - new XAttribute(W.author, settings.AuthorForRevisions), - new XAttribute(W.id, s_maxId++), - new XAttribute(W.date, settings.DateTimeForRevisions))); + trPr.Add( + new XElement( + revTrackElementName, + new XAttribute(W.author, settings.AuthorForRevisions), + new XAttribute(W.id, s_maxId++), + new XAttribute(W.date, settings.DateTimeForRevisions) + ) + ); } } } @@ -407,7 +423,8 @@ private static void MarkRowsAsDeletedOrInserted(WmlComparerSettings settings, Li private static List FlattenToComparisonUnitAtomList( List correlatedSequence, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var listOfComparisonUnitAtoms = correlatedSequence .Select(cs => @@ -420,27 +437,29 @@ private static List FlattenToComparisonUnitAtomList( if (cs.CorrelationStatus == CorrelationStatus.Equal) { var contentAtomsBefore = cs - .ComparisonUnitArray1 - .Select(ca => ca.DescendantContentAtoms()) + .ComparisonUnitArray1.Select(ca => ca.DescendantContentAtoms()) .SelectMany(m => m); var contentAtomsAfter = cs - .ComparisonUnitArray2 - .Select(ca => ca.DescendantContentAtoms()) + .ComparisonUnitArray2.Select(ca => ca.DescendantContentAtoms()) .SelectMany(m => m); var comparisonUnitAtomList = contentAtomsBefore - .Zip(contentAtomsAfter, - (before, after) => new ComparisonUnitAtom( - after.ContentElement, - after.AncestorElements, - after.Part, - settings) - { - CorrelationStatus = CorrelationStatus.Equal, - ContentElementBefore = before.ContentElement, - ComparisonUnitAtomBefore = before - }) + .Zip( + contentAtomsAfter, + (before, after) => + new ComparisonUnitAtom( + after.ContentElement, + after.AncestorElements, + after.Part, + settings + ) + { + CorrelationStatus = CorrelationStatus.Equal, + ContentElementBefore = before.ContentElement, + ComparisonUnitAtomBefore = before, + } + ) .ToList(); return comparisonUnitAtomList; @@ -449,14 +468,17 @@ private static List FlattenToComparisonUnitAtomList( if (cs.CorrelationStatus == CorrelationStatus.Deleted) { var comparisonUnitAtomList = cs - .ComparisonUnitArray1 - .Select(ca => ca.DescendantContentAtoms()) + .ComparisonUnitArray1.Select(ca => ca.DescendantContentAtoms()) .SelectMany(m => m) - .Select(ca => - new ComparisonUnitAtom(ca.ContentElement, ca.AncestorElements, ca.Part, settings) - { - CorrelationStatus = CorrelationStatus.Deleted - }); + .Select(ca => new ComparisonUnitAtom( + ca.ContentElement, + ca.AncestorElements, + ca.Part, + settings + ) + { + CorrelationStatus = CorrelationStatus.Deleted, + }); return comparisonUnitAtomList; } @@ -464,14 +486,17 @@ private static List FlattenToComparisonUnitAtomList( if (cs.CorrelationStatus == CorrelationStatus.Inserted) { var comparisonUnitAtomList = cs - .ComparisonUnitArray2 - .Select(ca => ca.DescendantContentAtoms()) + .ComparisonUnitArray2.Select(ca => ca.DescendantContentAtoms()) .SelectMany(m => m) - .Select(ca => - new ComparisonUnitAtom(ca.ContentElement, ca.AncestorElements, ca.Part, settings) - { - CorrelationStatus = CorrelationStatus.Inserted - }); + .Select(ca => new ComparisonUnitAtom( + ca.ContentElement, + ca.AncestorElements, + ca.Part, + settings + ) + { + CorrelationStatus = CorrelationStatus.Inserted, + }); return comparisonUnitAtomList; } @@ -527,7 +552,9 @@ private static List FlattenToComparisonUnitAtomList( /// document, but their ancestors actually point to the same paragraph. /// /// Fix this in the algorithm, and also keep the appropriate list in ComparisonUnitAtom class. - private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List comparisonUnitAtomList) + private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly( + List comparisonUnitAtomList + ) { if (False) { @@ -564,12 +591,7 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List - new - { - After = a, - Before = b - }); + var zipped = ancestorsBefore.Zip(ancestorsAfter, (b, a) => new { After = a, Before = b }); foreach (var z in zipped) { @@ -592,8 +614,7 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List) comparisonUnitAtomList).Reverse().ToList(); + var rComparisonUnitAtomList = ((IEnumerable)comparisonUnitAtomList).Reverse().ToList(); // the following should always succeed, because there will always be at least one element in // rComparisonUnitAtomList, and there will always be at least one ancestor in AncestorElements @@ -602,7 +623,7 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List ae.Name == W.txbxContent); + var pPr_inTextBox = cua.AncestorElements.Any(ae => ae.Name == W.txbxContent); if (!pPr_inTextBox) { // this will collect the ancestor unids for the paragraph. // my hypothesis is that these ancestor unids should be the same for all content unit atoms within that paragraph. currentAncestorUnids = cua - .AncestorElements - .Select(ae => + .AncestorElements.Select(ae => { - var thisUnid = (string) ae.Attribute(PtOpenXml.Unid); + var thisUnid = (string)ae.Attribute(PtOpenXml.Unid); if (thisUnid == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -647,18 +665,15 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List { - var thisUnid = (string) ae.Attribute(PtOpenXml.Unid); + var thisUnid = (string)ae.Attribute(PtOpenXml.Unid); if (thisUnid == null) Guid.NewGuid().ToString().Replace("-", ""); return thisUnid; }); - var thisAncestorUnids = currentAncestorUnids - .Concat(additionalAncestorUnids) - .ToArray(); + var thisAncestorUnids = currentAncestorUnids.Concat(additionalAncestorUnids).ToArray(); cua.AncestorUnids = thisAncestorUnids; if (deepestAncestorUnid != null) cua.AncestorUnids[0] = deepestAncestorUnid; @@ -696,9 +711,7 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List ae.Name == W.txbxContent); + var pPr_inTextBox = cua.AncestorElements.Any(ae => ae.Name == W.txbxContent); if (!pPr_inTextBox) { @@ -710,10 +723,9 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List + .AncestorElements.Select(ae => { - var thisUnid = (string) ae.Attribute(PtOpenXml.Unid); + var thisUnid = (string)ae.Attribute(PtOpenXml.Unid); if (thisUnid == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -729,18 +741,15 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List { - var thisUnid = (string) ae.Attribute(PtOpenXml.Unid); + var thisUnid = (string)ae.Attribute(PtOpenXml.Unid); if (thisUnid == null) Guid.NewGuid().ToString().Replace("-", ""); return thisUnid; }); - var thisAncestorUnids = currentAncestorUnids - .Concat(additionalAncestorUnids) - .ToArray(); + var thisAncestorUnids = currentAncestorUnids.Concat(additionalAncestorUnids).ToArray(); cua.AncestorUnids = thisAncestorUnids; } @@ -757,7 +766,8 @@ private static void AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(List comparisonUnitAtomList, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { // fabricate new MainDocumentPart from correlatedSequence s_maxId = 0; @@ -781,53 +791,66 @@ private static object MarkContentAsDeletedOrInsertedTransform(XNode node, WmlCom .DescendantsTrimmed(W.txbxContent) .Where(d => d.Name == W.t || d.Name == W.delText || AllowableRunChildren.Contains(d.Name)) .Attributes(PtOpenXml.Status) - .Select(a => (string) a) + .Select(a => (string)a) .Distinct() .ToList(); if (statusList.Count > 1) { throw new OpenXmlPowerToolsException( - "Internal error - have both deleted and inserted text elements in the same run."); + "Internal error - have both deleted and inserted text elements in the same run." + ); } if (statusList.Count == 0) { - return new XElement(W.r, + return new XElement( + W.r, element.Attributes(), - element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings))); + element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)) + ); } if (statusList.First() == "Deleted") { - return new XElement(W.del, + return new XElement( + W.del, new XAttribute(W.author, settings.AuthorForRevisions), new XAttribute(W.id, s_maxId++), new XAttribute(W.date, settings.DateTimeForRevisions), - new XElement(W.r, + new XElement( + W.r, element.Attributes(), - element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)))); + element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)) + ) + ); } if (statusList.First() == "Inserted") { - return new XElement(W.ins, + return new XElement( + W.ins, new XAttribute(W.author, settings.AuthorForRevisions), new XAttribute(W.id, s_maxId++), new XAttribute(W.date, settings.DateTimeForRevisions), - new XElement(W.r, + new XElement( + W.r, element.Attributes(), - element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)))); + element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)) + ) + ); } } if (element.Name == W.pPr) { - var status = (string) element.Attribute(PtOpenXml.Status); + var status = (string)element.Attribute(PtOpenXml.Status); if (status == null) - return new XElement(W.pPr, + return new XElement( + W.pPr, element.Attributes(), - element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings))); + element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)) + ); var pPr = new XElement(element); if (status == "Deleted") @@ -835,10 +858,14 @@ private static object MarkContentAsDeletedOrInsertedTransform(XNode node, WmlCom var rPr = pPr.Element(W.rPr); if (rPr == null) rPr = new XElement(W.rPr); - rPr.Add(new XElement(W.del, - new XAttribute(W.author, settings.AuthorForRevisions), - new XAttribute(W.id, s_maxId++), - new XAttribute(W.date, settings.DateTimeForRevisions))); + rPr.Add( + new XElement( + W.del, + new XAttribute(W.author, settings.AuthorForRevisions), + new XAttribute(W.id, s_maxId++), + new XAttribute(W.date, settings.DateTimeForRevisions) + ) + ); if (pPr.Element(W.rPr) != null) pPr.Element(W.rPr).ReplaceWith(rPr); else @@ -847,10 +874,14 @@ private static object MarkContentAsDeletedOrInsertedTransform(XNode node, WmlCom else if (status == "Inserted") { var rPr = pPr.Element(W.rPr) ?? new XElement(W.rPr); - rPr.Add(new XElement(W.ins, - new XAttribute(W.author, settings.AuthorForRevisions), - new XAttribute(W.id, s_maxId++), - new XAttribute(W.date, settings.DateTimeForRevisions))); + rPr.Add( + new XElement( + W.ins, + new XAttribute(W.author, settings.AuthorForRevisions), + new XAttribute(W.id, s_maxId++), + new XAttribute(W.date, settings.DateTimeForRevisions) + ) + ); if (pPr.Element(W.rPr) != null) pPr.Element(W.rPr).ReplaceWith(rPr); else @@ -864,9 +895,11 @@ private static object MarkContentAsDeletedOrInsertedTransform(XNode node, WmlCom return pPr; } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings))); + element.Nodes().Select(n => MarkContentAsDeletedOrInsertedTransform(n, settings)) + ); } return node; @@ -889,7 +922,7 @@ private static void IgnorePt14Namespace(XElement root) root.Add(new XAttribute(XNamespace.Xmlns + "pt14", PtOpenXml.pt.NamespaceName)); } - var ignorable = (string) root.Attribute(MC.Ignorable); + var ignorable = (string)root.Attribute(MC.Ignorable); if (ignorable is not null) { var list = ignorable.Split(' '); @@ -910,7 +943,8 @@ private static void ProcessFootnoteEndnote( List listOfComparisonUnitAtoms, MainDocumentPart mainDocumentPartBefore, MainDocumentPart mainDocumentPartAfter, - XDocument mainDocumentXDoc) + XDocument mainDocumentXDoc + ) { var footnotesPartBefore = mainDocumentPartBefore.FootnotesPart; var endnotesPartBefore = mainDocumentPartBefore.EndnotesPart; @@ -932,16 +966,16 @@ private static void ProcessFootnoteEndnote( var possiblyModifiedFootnotesEndNotes = listOfComparisonUnitAtoms .Where(cua => - cua.ContentElement.Name == W.footnoteReference || - cua.ContentElement.Name == W.endnoteReference) + cua.ContentElement.Name == W.footnoteReference || cua.ContentElement.Name == W.endnoteReference + ) .ToList(); foreach (var fn in possiblyModifiedFootnotesEndNotes) { string beforeId = null; if (fn.ContentElementBefore != null) - beforeId = (string) fn.ContentElementBefore.Attribute(W.id); - var afterId = (string) fn.ContentElement.Attribute(W.id); + beforeId = (string)fn.ContentElementBefore.Attribute(W.id); + var afterId = (string)fn.ContentElement.Attribute(W.id); XElement footnoteEndnoteBefore = null; XElement footnoteEndnoteAfter = null; @@ -955,13 +989,11 @@ private static void ProcessFootnoteEndnote( if (fn.ContentElement.Name == W.footnoteReference) { footnoteEndnoteBefore = footnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == beforeId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == beforeId); footnoteEndnoteAfter = footnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseBefore = footnotesPartBefore; partToUseAfter = footnotesPartAfter; partToUseBeforeXDoc = footnotesPartBeforeXDoc; @@ -970,13 +1002,11 @@ private static void ProcessFootnoteEndnote( else { footnoteEndnoteBefore = endnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == beforeId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == beforeId); footnoteEndnoteAfter = endnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseBefore = endnotesPartBefore; partToUseAfter = endnotesPartAfter; partToUseBeforeXDoc = endnotesPartBeforeXDoc; @@ -1010,8 +1040,10 @@ private static void ProcessFootnoteEndnote( MarkRowsAsDeletedOrInserted(settings, fnCorrelatedSequence); // the following gets a flattened list of ComparisonUnitAtoms, with status indicated in each ComparisonUnitAtom: Deleted, Inserted, or Equal - var fnListOfComparisonUnitAtoms = - FlattenToComparisonUnitAtomList(fnCorrelatedSequence, settings); + var fnListOfComparisonUnitAtoms = FlattenToComparisonUnitAtomList( + fnCorrelatedSequence, + settings + ); if (False) { @@ -1032,19 +1064,26 @@ private static void ProcessFootnoteEndnote( // in the case where a row is inserted, not necessary to hack - the inserted row ID will do as well. AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(fnListOfComparisonUnitAtoms); - var newFootnoteEndnoteChildren = - ProduceNewWmlMarkupFromCorrelatedSequence(partToUseAfter, fnListOfComparisonUnitAtoms, settings); + var newFootnoteEndnoteChildren = ProduceNewWmlMarkupFromCorrelatedSequence( + partToUseAfter, + fnListOfComparisonUnitAtoms, + settings + ); var tempElement = new XElement(W.body, newFootnoteEndnoteChildren); - var hasFootnoteReference = tempElement.Descendants(W.r).Any(r => - { - var b = false; - if ((string) r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() == - "FootnoteReference") - b = true; - if (r.Descendants(W.footnoteRef).Any()) - b = true; - return b; - }); + var hasFootnoteReference = tempElement + .Descendants(W.r) + .Any(r => + { + var b = false; + if ( + (string)r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() + == "FootnoteReference" + ) + b = true; + if (r.Descendants(W.footnoteRef).Any()) + b = true; + return b; + }); if (!hasFootnoteReference) { var firstPara = tempElement.Descendants(W.p).FirstOrDefault(); @@ -1055,24 +1094,33 @@ private static void ProcessFootnoteEndnote( { if (fn.ContentElement.Name == W.footnoteReference) firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "FootnoteReference"))), - new XElement(W.footnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "FootnoteReference")) + ), + new XElement(W.footnoteRef) + ) + ); else firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "EndnoteReference"))), - new XElement(W.endnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "EndnoteReference")) + ), + new XElement(W.endnoteRef) + ) + ); } } } - var newTempElement = (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); - var newContentElement = newTempElement.Descendants() + var newTempElement = (XElement)WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); + var newContentElement = newTempElement + .Descendants() .FirstOrDefault(d => d.Name == W.footnote || d.Name == W.endnote); if (newContentElement == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -1085,18 +1133,16 @@ private static void ProcessFootnoteEndnote( if (fn.ContentElement.Name == W.footnoteReference) { footnoteEndnoteAfter = footnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseAfter = footnotesPartAfter; partToUseAfterXDoc = footnotesPartAfterXDoc; } else { footnoteEndnoteAfter = endnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseAfter = endnotesPartAfter; partToUseAfterXDoc = endnotesPartAfterXDoc; } @@ -1112,8 +1158,8 @@ private static void ProcessFootnoteEndnote( { ComparisonUnitArray1 = null, ComparisonUnitArray2 = fncus2, - CorrelationStatus = CorrelationStatus.Inserted - } + CorrelationStatus = CorrelationStatus.Inserted, + }, }; if (False) @@ -1127,24 +1173,30 @@ private static void ProcessFootnoteEndnote( MarkRowsAsDeletedOrInserted(settings, insertedCorrSequ); - var fnListOfComparisonUnitAtoms = - FlattenToComparisonUnitAtomList(insertedCorrSequ, settings); + var fnListOfComparisonUnitAtoms = FlattenToComparisonUnitAtomList(insertedCorrSequ, settings); AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(fnListOfComparisonUnitAtoms); - var newFootnoteEndnoteChildren = ProduceNewWmlMarkupFromCorrelatedSequence(partToUseAfter, - fnListOfComparisonUnitAtoms, settings); + var newFootnoteEndnoteChildren = ProduceNewWmlMarkupFromCorrelatedSequence( + partToUseAfter, + fnListOfComparisonUnitAtoms, + settings + ); var tempElement = new XElement(W.body, newFootnoteEndnoteChildren); - var hasFootnoteReference = tempElement.Descendants(W.r).Any(r => - { - var b = false; - if ((string) r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() == - "FootnoteReference") - b = true; - if (r.Descendants(W.footnoteRef).Any()) - b = true; - return b; - }); + var hasFootnoteReference = tempElement + .Descendants(W.r) + .Any(r => + { + var b = false; + if ( + (string)r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() + == "FootnoteReference" + ) + b = true; + if (r.Descendants(W.footnoteRef).Any()) + b = true; + return b; + }); if (!hasFootnoteReference) { var firstPara = tempElement.Descendants(W.p).FirstOrDefault(); @@ -1155,23 +1207,31 @@ private static void ProcessFootnoteEndnote( { if (fn.ContentElement.Name == W.footnoteReference) firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "FootnoteReference"))), - new XElement(W.footnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "FootnoteReference")) + ), + new XElement(W.footnoteRef) + ) + ); else firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "EndnoteReference"))), - new XElement(W.endnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "EndnoteReference")) + ), + new XElement(W.endnoteRef) + ) + ); } } } - var newTempElement = (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); + var newTempElement = (XElement)WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); var newContentElement = newTempElement .Descendants() .FirstOrDefault(d => d.Name == W.footnote || d.Name == W.endnote); @@ -1185,18 +1245,16 @@ private static void ProcessFootnoteEndnote( if (fn.ContentElement.Name == W.footnoteReference) { footnoteEndnoteBefore = footnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseAfter = footnotesPartAfter; partToUseAfterXDoc = footnotesPartAfterXDoc; } else { footnoteEndnoteBefore = endnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(fnn => (string) fnn.Attribute(W.id) == afterId); + .Root.Elements() + .FirstOrDefault(fnn => (string)fnn.Attribute(W.id) == afterId); partToUseBefore = endnotesPartBefore; partToUseBeforeXDoc = endnotesPartBeforeXDoc; } @@ -1212,8 +1270,8 @@ private static void ProcessFootnoteEndnote( { ComparisonUnitArray1 = fncus2, ComparisonUnitArray2 = null, - CorrelationStatus = CorrelationStatus.Deleted - } + CorrelationStatus = CorrelationStatus.Deleted, + }, }; if (False) @@ -1227,26 +1285,32 @@ private static void ProcessFootnoteEndnote( MarkRowsAsDeletedOrInserted(settings, deletedCorrSequ); - var fnListOfComparisonUnitAtoms = - FlattenToComparisonUnitAtomList(deletedCorrSequ, settings); + var fnListOfComparisonUnitAtoms = FlattenToComparisonUnitAtomList(deletedCorrSequ, settings); if (fnListOfComparisonUnitAtoms.Any()) { AssembleAncestorUnidsInOrderToRebuildXmlTreeProperly(fnListOfComparisonUnitAtoms); - var newFootnoteEndnoteChildren = ProduceNewWmlMarkupFromCorrelatedSequence(partToUseBefore, - fnListOfComparisonUnitAtoms, settings); + var newFootnoteEndnoteChildren = ProduceNewWmlMarkupFromCorrelatedSequence( + partToUseBefore, + fnListOfComparisonUnitAtoms, + settings + ); var tempElement = new XElement(W.body, newFootnoteEndnoteChildren); - var hasFootnoteReference = tempElement.Descendants(W.r).Any(r => - { - var b = false; - if ((string) r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() == - "FootnoteReference") - b = true; - if (r.Descendants(W.footnoteRef).Any()) - b = true; - return b; - }); + var hasFootnoteReference = tempElement + .Descendants(W.r) + .Any(r => + { + var b = false; + if ( + (string)r.Elements(W.rPr).Elements(W.rStyle).Attributes(W.val).FirstOrDefault() + == "FootnoteReference" + ) + b = true; + if (r.Descendants(W.footnoteRef).Any()) + b = true; + return b; + }); if (!hasFootnoteReference) { var firstPara = tempElement.Descendants(W.p).FirstOrDefault(); @@ -1257,24 +1321,33 @@ private static void ProcessFootnoteEndnote( { if (fn.ContentElement.Name == W.footnoteReference) firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "FootnoteReference"))), - new XElement(W.footnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "FootnoteReference")) + ), + new XElement(W.footnoteRef) + ) + ); else firstRun.AddBeforeSelf( - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.rStyle, - new XAttribute(W.val, "EndnoteReference"))), - new XElement(W.endnoteRef))); + new XElement( + W.r, + new XElement( + W.rPr, + new XElement(W.rStyle, new XAttribute(W.val, "EndnoteReference")) + ), + new XElement(W.endnoteRef) + ) + ); } } } - var newTempElement = (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); - var newContentElement = newTempElement.Descendants() + var newTempElement = (XElement)WordprocessingMLUtil.WmlOrderElementsPerStandard(tempElement); + var newContentElement = newTempElement + .Descendants() .FirstOrDefault(d => d.Name == W.footnote || d.Name == W.endnote); if (newContentElement == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -1294,7 +1367,8 @@ private static void RectifyFootnoteEndnoteIds( MainDocumentPart mainDocumentPartAfter, MainDocumentPart mainDocumentPartWithRevisions, XDocument mainDocumentXDoc, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var footnotesPartBefore = mainDocumentPartBefore.FootnotesPart; var endnotesPartBefore = mainDocumentPartBefore.EndnotesPart; @@ -1316,9 +1390,8 @@ private static void RectifyFootnoteEndnoteIds( { footnotesPartWithRevisionsXDoc = footnotesPartWithRevisions.GetXDocument(); footnotesPartWithRevisionsXDoc - .Root - .Elements(W.footnote) - .Where(e => (string) e.Attribute(W.id) != "-1" && (string) e.Attribute(W.id) != "0") + .Root.Elements(W.footnote) + .Where(e => (string)e.Attribute(W.id) != "-1" && (string)e.Attribute(W.id) != "0") .Remove(); } @@ -1335,38 +1408,33 @@ private static void RectifyFootnoteEndnoteIds( { endnotesPartWithRevisionsXDoc = endnotesPartWithRevisions.GetXDocument(); endnotesPartWithRevisionsXDoc - .Root - .Elements(W.endnote) - .Where(e => (string) e.Attribute(W.id) != "-1" && (string) e.Attribute(W.id) != "0") + .Root.Elements(W.endnote) + .Where(e => (string)e.Attribute(W.id) != "-1" && (string)e.Attribute(W.id) != "0") .Remove(); } var footnotesRefs = mainDocumentXDoc .Descendants(W.footnoteReference) - .Select((fn, idx) => - { - return new + .Select( + (fn, idx) => { - FootNote = fn, - Idx = idx - }; - }); + return new { FootNote = fn, Idx = idx }; + } + ); foreach (var fn in footnotesRefs) { - var oldId = (string) fn.FootNote.Attribute(W.id); + var oldId = (string)fn.FootNote.Attribute(W.id); var newId = (fn.Idx + 1).ToString(); fn.FootNote.Attribute(W.id).Value = newId; var footnote = footnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + .Root.Elements() + .FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); if (footnote == null) { footnote = footnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + .Root.Elements() + .FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); } if (footnote == null) @@ -1374,37 +1442,31 @@ private static void RectifyFootnoteEndnoteIds( var cloned = new XElement(footnote); cloned.Attribute(W.id).Value = newId; - footnotesPartWithRevisionsXDoc - .Root - .Add(cloned); + footnotesPartWithRevisionsXDoc.Root.Add(cloned); } var endnotesRefs = mainDocumentXDoc .Descendants(W.endnoteReference) - .Select((fn, idx) => - { - return new + .Select( + (fn, idx) => { - Endnote = fn, - Idx = idx - }; - }); + return new { Endnote = fn, Idx = idx }; + } + ); foreach (var fn in endnotesRefs) { - var oldId = (string) fn.Endnote.Attribute(W.id); + var oldId = (string)fn.Endnote.Attribute(W.id); var newId = (fn.Idx + 1).ToString(); fn.Endnote.Attribute(W.id).Value = newId; var endnote = endnotesPartAfterXDoc - .Root - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + .Root.Elements() + .FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); if (endnote == null) { endnote = endnotesPartBeforeXDoc - .Root - .Elements() - .FirstOrDefault(e => (string) e.Attribute(W.id) == oldId); + .Root.Elements() + .FirstOrDefault(e => (string)e.Attribute(W.id) == oldId); } if (endnote == null) @@ -1412,17 +1474,15 @@ private static void RectifyFootnoteEndnoteIds( var cloned = new XElement(endnote); cloned.Attribute(W.id).Value = newId; - endnotesPartWithRevisionsXDoc - .Root - .Add(cloned); + endnotesPartWithRevisionsXDoc.Root.Add(cloned); } if (footnotesPartWithRevisionsXDoc != null) { MarkContentAsDeletedOrInserted(footnotesPartWithRevisionsXDoc, settings); CoalesceAdjacentRunsWithIdenticalFormatting(footnotesPartWithRevisionsXDoc); - var newXDocRoot = - (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(footnotesPartWithRevisionsXDoc.Root); + var newXDocRoot = (XElement) + WordprocessingMLUtil.WmlOrderElementsPerStandard(footnotesPartWithRevisionsXDoc.Root); footnotesPartWithRevisionsXDoc.Root.ReplaceWith(newXDocRoot); IgnorePt14Namespace(footnotesPartWithRevisionsXDoc.Root); footnotesPartWithRevisions.PutXDocument(); @@ -1432,7 +1492,8 @@ private static void RectifyFootnoteEndnoteIds( { MarkContentAsDeletedOrInserted(endnotesPartWithRevisionsXDoc, settings); CoalesceAdjacentRunsWithIdenticalFormatting(endnotesPartWithRevisionsXDoc); - var newXDocRoot = (XElement) WordprocessingMLUtil.WmlOrderElementsPerStandard(endnotesPartWithRevisionsXDoc.Root); + var newXDocRoot = (XElement) + WordprocessingMLUtil.WmlOrderElementsPerStandard(endnotesPartWithRevisionsXDoc.Root); endnotesPartWithRevisionsXDoc.Root.ReplaceWith(newXDocRoot); IgnorePt14Namespace(endnotesPartWithRevisionsXDoc.Root); endnotesPartWithRevisions.PutXDocument(); @@ -1476,16 +1537,16 @@ private static object ConjoinTransform(XNode node) var pPr = new XElement(element.Elements(W.pPr).First()); pPr.Elements(W.rPr).Elements().Where(r => r.Name == W.ins || r.Name == W.del).Remove(); pPr.Attributes(PtOpenXml.Status).Remove(); - var newPara = new XElement(W.p, + var newPara = new XElement( + W.p, element.Attributes(), pPr, - element.Elements().Where(c => c.Name != W.pPr)); + element.Elements().Where(c => c.Name != W.pPr) + ); return newPara; } - return new XElement(element.Name, - element.Attributes(), - element.Nodes().Select(ConjoinTransform)); + return new XElement(element.Name, element.Attributes(), element.Nodes().Select(ConjoinTransform)); } return node; @@ -1497,34 +1558,26 @@ private static void FixUpRevisionIds(WordprocessingDocument wDocWithRevisions, X if (wDocWithRevisions.MainDocumentPart.FootnotesPart != null) { var fnxd = wDocWithRevisions.MainDocumentPart.FootnotesPart.GetXDocument(); - footnoteRevisions = fnxd - .Descendants() - .Where(d => d.Name == W.ins || d.Name == W.del); + footnoteRevisions = fnxd.Descendants().Where(d => d.Name == W.ins || d.Name == W.del); } var endnoteRevisions = Enumerable.Empty(); if (wDocWithRevisions.MainDocumentPart.EndnotesPart != null) { var fnxd = wDocWithRevisions.MainDocumentPart.EndnotesPart.GetXDocument(); - endnoteRevisions = fnxd - .Descendants() - .Where(d => d.Name == W.ins || d.Name == W.del); + endnoteRevisions = fnxd.Descendants().Where(d => d.Name == W.ins || d.Name == W.del); } - var mainRevisions = newXDoc - .Descendants() - .Where(d => d.Name == W.ins || d.Name == W.del); + var mainRevisions = newXDoc.Descendants().Where(d => d.Name == W.ins || d.Name == W.del); var allRevisions = mainRevisions .Concat(footnoteRevisions) .Concat(endnoteRevisions) - .Select((r, i) => - { - return new + .Select( + (r, i) => { - Rev = r, - Idx = i + 1 - }; - }); + return new { Rev = r, Idx = i + 1 }; + } + ); foreach (var item in allRevisions) item.Rev.Attribute(W.id).Value = item.Idx.ToString(); if (wDocWithRevisions.MainDocumentPart.FootnotesPart != null) @@ -1536,8 +1589,7 @@ private static void FixUpRevisionIds(WordprocessingDocument wDocWithRevisions, X private static void MoveLastSectPrToChildOfBody(XDocument newXDoc) { var lastParaWithSectPr = newXDoc - .Root - .Elements(W.body) + .Root.Elements(W.body) .Elements(W.p) .LastOrDefault(p => p.Elements(W.pPr).Elements(W.sectPr).Any()); if (lastParaWithSectPr != null) @@ -1547,7 +1599,7 @@ private static void MoveLastSectPrToChildOfBody(XDocument newXDoc) } } - private static void FixUpFootnotesEndnotesWithCustomMarkers(WordprocessingDocument wDocWithRevisions) + private static void FixUpFootnotesEndnotesWithCustomMarkers(WordprocessingDocument wDocWithRevisions) { #if FALSE @@ -1623,7 +1675,7 @@ private static void FixUpFootnotesEndnotesWithCustomMarkers(WordprocessingDocume // this is pretty random - a bug in Word prevents display of a document if the delText element does not immediately follow the footnoteReference element, in the same run. var mainXDoc = wDocWithRevisions.MainDocumentPart.GetXDocument(); - var newRoot = (XElement) FootnoteEndnoteReferenceCleanupTransform(mainXDoc.Root); + var newRoot = (XElement)FootnoteEndnoteReferenceCleanupTransform(mainXDoc.Root); mainXDoc.Root?.ReplaceWith(newRoot); wDocWithRevisions.MainDocumentPart.PutXDocument(); } @@ -1646,9 +1698,11 @@ private static object FootnoteEndnoteReferenceCleanupTransform(XNode node) if (hasFootnoteEndnoteReferencesThatNeedCleanedUp) { - var clone = new XElement(element.Name, + var clone = new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => FootnoteEndnoteReferenceCleanupTransform(n))); + element.Nodes().Select(n => FootnoteEndnoteReferenceCleanupTransform(n)) + ); var footnoteEndnoteReferencesToAdjust = clone .Descendants() .Where(d => d.Name == W.footnoteReference || d.Name == W.endnoteReference) @@ -1657,8 +1711,7 @@ private static object FootnoteEndnoteReferenceCleanupTransform(XNode node) { var par = fnenr.Parent; var gp = fnenr.Parent.Parent; - if (par.Name == W.r && - gp.Name == W.del) + if (par.Name == W.r && gp.Name == W.del) { if (par.Element(W.delText) != null) continue; @@ -1675,8 +1728,7 @@ private static object FootnoteEndnoteReferenceCleanupTransform(XNode node) } } - if (par.Name == W.r && - gp.Name == W.ins) + if (par.Name == W.r && gp.Name == W.ins) { if (par.Element(W.t) != null) continue; @@ -1699,9 +1751,11 @@ private static object FootnoteEndnoteReferenceCleanupTransform(XNode node) } else { - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(FootnoteEndnoteReferenceCleanupTransform)); + element.Nodes().Select(FootnoteEndnoteReferenceCleanupTransform) + ); } } @@ -1710,8 +1764,7 @@ private static object FootnoteEndnoteReferenceCleanupTransform(XNode node) private static void FixUpRevMarkIds(WordprocessingDocument wDoc) { - var revMarksToChange = wDoc - .ContentParts() + var revMarksToChange = wDoc.ContentParts() .Select(cp => cp.GetXDocument()) .Select(xd => xd.Descendants().Where(d => d.Name == W.ins || d.Name == W.del)) .SelectMany(m => m); @@ -1730,8 +1783,7 @@ private static void FixUpRevMarkIds(WordprocessingDocument wDoc) private static void FixUpDocPrIds(WordprocessingDocument wDoc) { var elementToFind = WP.docPr; - var docPrToChange = wDoc - .ContentParts() + var docPrToChange = wDoc.ContentParts() .Select(cp => cp.GetXDocument()) .Select(xd => xd.Descendants().Where(d => d.Name == elementToFind)) .SelectMany(m => m); @@ -1750,8 +1802,7 @@ private static void FixUpDocPrIds(WordprocessingDocument wDoc) private static void FixUpShapeIds(WordprocessingDocument wDoc) { var elementToFind = VML.shape; - var shapeIdsToChange = wDoc - .ContentParts() + var shapeIdsToChange = wDoc.ContentParts() .Select(cp => cp.GetXDocument()) .Select(xd => xd.Descendants().Where(d => d.Name == elementToFind)) .SelectMany(m => m); @@ -1780,8 +1831,7 @@ private static void FixUpShapeIds(WordprocessingDocument wDoc) private static void FixUpShapeTypeIds(WordprocessingDocument wDoc) { var elementToFind = VML.shapetype; - var shapeTypeIdsToChange = wDoc - .ContentParts() + var shapeTypeIdsToChange = wDoc.ContentParts() .Select(cp => cp.GetXDocument()) .Select(xd => xd.Descendants().Where(d => d.Name == elementToFind)) .SelectMany(m => m); @@ -1817,9 +1867,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe if (hasFootnotes) { var footnoteTextStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "FootnoteText"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "FootnoteText"); if (footnoteTextStyle == null) { var footnoteTextStyleMarkup = @@ -1847,9 +1896,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe } var footnoteTextCharStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "FootnoteTextChar"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "FootnoteTextChar"); if (footnoteTextCharStyle == null) { var footnoteTextCharStyleMarkup = @@ -1872,9 +1920,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe } var footnoteReferenceStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "FootnoteReference"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "FootnoteReference"); if (footnoteReferenceStyle == null) { var footnoteReferenceStyleMarkup = @@ -1898,9 +1945,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe if (hasEndnotes) { var endnoteTextStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "EndnoteText"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "EndnoteText"); if (endnoteTextStyle == null) { var endnoteTextStyleMarkup = @@ -1928,9 +1974,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe } var endnoteTextCharStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "EndnoteTextChar"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "EndnoteTextChar"); if (endnoteTextCharStyle == null) { var endnoteTextCharStyleMarkup = @@ -1953,9 +1998,8 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe } var endnoteReferenceStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "EndnoteReference"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "EndnoteReference"); if (endnoteReferenceStyle == null) { var endnoteReferenceStyleMarkup = @@ -1982,19 +2026,22 @@ private static void AddFootnotesEndnotesStyles(WordprocessingDocument wDocWithRe } } - private static void CopyMissingStylesFromOneDocToAnother(WordprocessingDocument wDocFrom, WordprocessingDocument wDocTo) + private static void CopyMissingStylesFromOneDocToAnother( + WordprocessingDocument wDocFrom, + WordprocessingDocument wDocTo + ) { var revisionsStylesXDoc = wDocTo.MainDocumentPart.StyleDefinitionsPart.GetXDocument(); var afterStylesXDoc = wDocFrom.MainDocumentPart.StyleDefinitionsPart.GetXDocument(); foreach (var style in afterStylesXDoc.Root.Elements(W.style)) { - var type = (string) style.Attribute(W.type); - var styleId = (string) style.Attribute(W.styleId); + var type = (string)style.Attribute(W.type); + var styleId = (string)style.Attribute(W.styleId); var styleInRevDoc = revisionsStylesXDoc - .Root - .Elements(W.style) - .FirstOrDefault(st => (string) st.Attribute(W.type) == type && - (string) st.Attribute(W.styleId) == styleId); + .Root.Elements(W.style) + .FirstOrDefault(st => + (string)st.Attribute(W.type) == type && (string)st.Attribute(W.styleId) == styleId + ); if (styleInRevDoc != null) continue; @@ -2022,9 +2069,11 @@ private static object CloneForStructureHash(XNode node) { if (node is XElement element) { - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(CloneForStructureHash)); + element.Elements().Select(CloneForStructureHash) + ); } return null; @@ -2032,23 +2081,21 @@ private static object CloneForStructureHash(XNode node) private static List FindCommonAtBeginningAndEnd( CorrelatedSequence unknown, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var lengthToCompare = Math.Min(unknown.ComparisonUnitArray1.Length, unknown.ComparisonUnitArray2.Length); var countCommonAtBeginning = unknown - .ComparisonUnitArray1 - .Take(lengthToCompare) - .Zip(unknown.ComparisonUnitArray2, - (pu1, pu2) => new - { - Pu1 = pu1, - Pu2 = pu2 - }) + .ComparisonUnitArray1.Take(lengthToCompare) + .Zip(unknown.ComparisonUnitArray2, (pu1, pu2) => new { Pu1 = pu1, Pu2 = pu2 }) .TakeWhile(pair => pair.Pu1.SHA1Hash == pair.Pu2.SHA1Hash) .Count(); - if (countCommonAtBeginning != 0 && countCommonAtBeginning / (double) lengthToCompare < settings.DetailThreshold) + if ( + countCommonAtBeginning != 0 + && countCommonAtBeginning / (double)lengthToCompare < settings.DetailThreshold + ) countCommonAtBeginning = 0; if (countCommonAtBeginning != 0) @@ -2058,14 +2105,8 @@ private static List FindCommonAtBeginningAndEnd( var csEqual = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Equal, - ComparisonUnitArray1 = unknown - .ComparisonUnitArray1 - .Take(countCommonAtBeginning) - .ToArray(), - ComparisonUnitArray2 = unknown - .ComparisonUnitArray2 - .Take(countCommonAtBeginning) - .ToArray() + ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Take(countCommonAtBeginning).ToArray(), + ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Take(countCommonAtBeginning).ToArray(), }; newSequence.Add(csEqual); @@ -2078,7 +2119,7 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Skip(countCommonAtBeginning).ToArray(), - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newSequence.Add(csDeleted); } @@ -2088,14 +2129,16 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Skip(countCommonAtBeginning).ToArray() + ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Skip(countCommonAtBeginning).ToArray(), }; newSequence.Add(csInserted); } else if (remainingLeft != 0 && remainingRight != 0) { - if (unknown.ComparisonUnitArray1[0] is ComparisonUnitWord first1 && - unknown.ComparisonUnitArray2[0] is ComparisonUnitWord first2) + if ( + unknown.ComparisonUnitArray1[0] is ComparisonUnitWord first1 + && unknown.ComparisonUnitArray2[0] is ComparisonUnitWord first2 + ) { // if operating at the word level and // if the last word on the left != pPr && last word on right != pPr @@ -2107,25 +2150,24 @@ private static List FindCommonAtBeginningAndEnd( // if the last word on the left == pPr and last word on right == pPr // then create an unknown for the rest of the unknown - var remainingInLeft = unknown - .ComparisonUnitArray1 - .Skip(countCommonAtBeginning) - .ToArray(); + var remainingInLeft = unknown.ComparisonUnitArray1.Skip(countCommonAtBeginning).ToArray(); - var remainingInRight = unknown - .ComparisonUnitArray2 - .Skip(countCommonAtBeginning) - .ToArray(); + var remainingInRight = unknown.ComparisonUnitArray2.Skip(countCommonAtBeginning).ToArray(); - var lastContentAtomLeft = unknown.ComparisonUnitArray1[countCommonAtBeginning - 1] + var lastContentAtomLeft = unknown + .ComparisonUnitArray1[countCommonAtBeginning - 1] .DescendantContentAtoms() .FirstOrDefault(); - var lastContentAtomRight = unknown.ComparisonUnitArray2[countCommonAtBeginning - 1] + var lastContentAtomRight = unknown + .ComparisonUnitArray2[countCommonAtBeginning - 1] .DescendantContentAtoms() .FirstOrDefault(); - if (lastContentAtomLeft?.ContentElement.Name != W.pPr && lastContentAtomRight?.ContentElement.Name != W.pPr) + if ( + lastContentAtomLeft?.ContentElement.Name != W.pPr + && lastContentAtomRight?.ContentElement.Name != W.pPr + ) { var split1 = SplitAtParagraphMark(remainingInLeft); var split2 = SplitAtParagraphMark(remainingInRight); @@ -2135,7 +2177,7 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = split1.First(), - ComparisonUnitArray2 = split2.First() + ComparisonUnitArray2 = split2.First(), }; newSequence.Add(csUnknown2); return newSequence; @@ -2147,7 +2189,7 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = split1.First(), - ComparisonUnitArray2 = split2.First() + ComparisonUnitArray2 = split2.First(), }; newSequence.Add(csUnknown2); @@ -2155,7 +2197,7 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = split1.Skip(1).First(), - ComparisonUnitArray2 = split2.Skip(1).First() + ComparisonUnitArray2 = split2.Skip(1).First(), }; newSequence.Add(csUnknown3); @@ -2168,7 +2210,7 @@ private static List FindCommonAtBeginningAndEnd( { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Skip(countCommonAtBeginning).ToArray(), - ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Skip(countCommonAtBeginning).ToArray() + ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Skip(countCommonAtBeginning).ToArray(), }; newSequence.Add(csUnknown); } @@ -2183,18 +2225,12 @@ private static List FindCommonAtBeginningAndEnd( // if we get to here, then countCommonAtBeginning == 0 var countCommonAtEnd = unknown - .ComparisonUnitArray1 - .Reverse() + .ComparisonUnitArray1.Reverse() .Take(lengthToCompare) - .Zip(unknown - .ComparisonUnitArray2 - .Reverse() - .Take(lengthToCompare), - (pu1, pu2) => new - { - Pu1 = pu1, - Pu2 = pu2 - }) + .Zip( + unknown.ComparisonUnitArray2.Reverse().Take(lengthToCompare), + (pu1, pu2) => new { Pu1 = pu1, Pu2 = pu2 } + ) .TakeWhile(pair => pair.Pu1.SHA1Hash == pair.Pu2.SHA1Hash) .Count(); @@ -2204,11 +2240,7 @@ private static List FindCommonAtBeginningAndEnd( if (countCommonAtEnd <= 1) break; - var firstCommon = unknown - .ComparisonUnitArray1 - .Reverse() - .Take(countCommonAtEnd) - .LastOrDefault(); + var firstCommon = unknown.ComparisonUnitArray1.Reverse().Take(countCommonAtEnd).LastOrDefault(); if (firstCommon is not ComparisonUnitWord firstCommonWord) break; @@ -2229,11 +2261,7 @@ private static List FindCommonAtBeginningAndEnd( var isOnlyParagraphMark = false; if (countCommonAtEnd == 1) { - var firstCommon = unknown - .ComparisonUnitArray1 - .Reverse() - .Take(countCommonAtEnd) - .LastOrDefault(); + var firstCommon = unknown.ComparisonUnitArray1.Reverse().Take(countCommonAtEnd).LastOrDefault(); if (firstCommon is ComparisonUnitWord firstCommonWord) { @@ -2251,25 +2279,22 @@ private static List FindCommonAtBeginningAndEnd( if (countCommonAtEnd == 2) { - var firstCommon = unknown - .ComparisonUnitArray1 - .Reverse() - .Take(countCommonAtEnd) - .LastOrDefault(); + var firstCommon = unknown.ComparisonUnitArray1.Reverse().Take(countCommonAtEnd).LastOrDefault(); - var secondCommon = unknown - .ComparisonUnitArray1 - .Reverse() - .Take(countCommonAtEnd) - .FirstOrDefault(); + var secondCommon = unknown.ComparisonUnitArray1.Reverse().Take(countCommonAtEnd).FirstOrDefault(); - if (firstCommon is ComparisonUnitWord firstCommonWord && secondCommon is ComparisonUnitWord secondCommonWord) + if ( + firstCommon is ComparisonUnitWord firstCommonWord + && secondCommon is ComparisonUnitWord secondCommonWord + ) { // if the word contains more than one atom, then not a paragraph mark if (firstCommonWord.Contents.Count == 1 && secondCommonWord.Contents.Count == 1) { - if (firstCommonWord.Contents.First() is ComparisonUnitAtom firstCommonAtom && - secondCommonWord.Contents.First() is ComparisonUnitAtom secondCommonAtom) + if ( + firstCommonWord.Contents.First() is ComparisonUnitAtom firstCommonAtom + && secondCommonWord.Contents.First() is ComparisonUnitAtom secondCommonAtom + ) { if (secondCommonAtom.ContentElement.Name == W.pPr) isOnlyParagraphMark = true; @@ -2278,8 +2303,11 @@ private static List FindCommonAtBeginningAndEnd( } } - if (!isOnlyParagraphMark && countCommonAtEnd != 0 && - countCommonAtEnd / (double) lengthToCompare < settings.DetailThreshold) + if ( + !isOnlyParagraphMark + && countCommonAtEnd != 0 + && countCommonAtEnd / (double)lengthToCompare < settings.DetailThreshold + ) { countCommonAtEnd = 0; } @@ -2305,38 +2333,33 @@ private static List FindCommonAtBeginningAndEnd( var remainingInLeftParagraph = 0; var remainingInRightParagraph = 0; - var commonEndSeq = unknown - .ComparisonUnitArray1 - .Reverse() - .Take(countCommonAtEnd) - .Reverse() - .ToList(); + var commonEndSeq = unknown.ComparisonUnitArray1.Reverse().Take(countCommonAtEnd).Reverse().ToList(); var firstOfCommonEndSeq = commonEndSeq.First(); if (firstOfCommonEndSeq is ComparisonUnitWord) { // are there any paragraph marks in the common seq at end? //if (commonEndSeq.Any(cu => cu.Contents.OfType().First().ContentElement.Name == W.pPr)) - if (commonEndSeq.Any(cu => - { - var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); - if (firstComparisonUnitAtom == null) - return false; + if ( + commonEndSeq.Any(cu => + { + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); + if (firstComparisonUnitAtom == null) + return false; - return firstComparisonUnitAtom.ContentElement.Name == W.pPr; - })) + return firstComparisonUnitAtom.ContentElement.Name == W.pPr; + }) + ) { remainingInLeftParagraph = unknown - .ComparisonUnitArray1 - .Reverse() + .ComparisonUnitArray1.Reverse() .Skip(countCommonAtEnd) .TakeWhile(cu => { if (!(cu is ComparisonUnitWord)) return false; - var firstComparisonUnitAtom = - cu.Contents.OfType().FirstOrDefault(); + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); if (firstComparisonUnitAtom == null) return true; @@ -2344,16 +2367,14 @@ private static List FindCommonAtBeginningAndEnd( }) .Count(); remainingInRightParagraph = unknown - .ComparisonUnitArray2 - .Reverse() + .ComparisonUnitArray2.Reverse() .Skip(countCommonAtEnd) .TakeWhile(cu => { if (!(cu is ComparisonUnitWord)) return false; - var firstComparisonUnitAtom = - cu.Contents.OfType().FirstOrDefault(); + var firstComparisonUnitAtom = cu.Contents.OfType().FirstOrDefault(); if (firstComparisonUnitAtom == null) return true; @@ -2365,38 +2386,39 @@ private static List FindCommonAtBeginningAndEnd( var newSequence = new List(); - var beforeCommonParagraphLeft = unknown.ComparisonUnitArray1.Length - remainingInLeftParagraph - countCommonAtEnd; + var beforeCommonParagraphLeft = + unknown.ComparisonUnitArray1.Length - remainingInLeftParagraph - countCommonAtEnd; var beforeCommonParagraphRight = unknown.ComparisonUnitArray2.Length - remainingInRightParagraph - countCommonAtEnd; if (beforeCommonParagraphLeft != 0 && beforeCommonParagraphRight == 0) { var csDeleted = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Deleted, - ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Take(beforeCommonParagraphLeft).ToArray(), - ComparisonUnitArray2 = null - }; + { + CorrelationStatus = CorrelationStatus.Deleted, + ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Take(beforeCommonParagraphLeft).ToArray(), + ComparisonUnitArray2 = null, + }; newSequence.Add(csDeleted); } else if (beforeCommonParagraphLeft == 0 && beforeCommonParagraphRight != 0) { var csInserted = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Inserted, - ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Take(beforeCommonParagraphRight).ToArray() - }; + { + CorrelationStatus = CorrelationStatus.Inserted, + ComparisonUnitArray1 = null, + ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Take(beforeCommonParagraphRight).ToArray(), + }; newSequence.Add(csInserted); } else if (beforeCommonParagraphLeft != 0 && beforeCommonParagraphRight != 0) { var csUnknown = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Unknown, - ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Take(beforeCommonParagraphLeft).ToArray(), - ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Take(beforeCommonParagraphRight).ToArray() - }; + { + CorrelationStatus = CorrelationStatus.Unknown, + ComparisonUnitArray1 = unknown.ComparisonUnitArray1.Take(beforeCommonParagraphLeft).ToArray(), + ComparisonUnitArray2 = unknown.ComparisonUnitArray2.Take(beforeCommonParagraphRight).ToArray(), + }; newSequence.Add(csUnknown); } else if (beforeCommonParagraphLeft == 0 && beforeCommonParagraphRight == 0) @@ -2407,39 +2429,43 @@ private static List FindCommonAtBeginningAndEnd( if (remainingInLeftParagraph != 0 && remainingInRightParagraph == 0) { var csDeleted = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Deleted, - ComparisonUnitArray1 = unknown.ComparisonUnitArray1 - .Skip(beforeCommonParagraphLeft) - .Take(remainingInLeftParagraph).ToArray(), - ComparisonUnitArray2 = null - }; + { + CorrelationStatus = CorrelationStatus.Deleted, + ComparisonUnitArray1 = unknown + .ComparisonUnitArray1.Skip(beforeCommonParagraphLeft) + .Take(remainingInLeftParagraph) + .ToArray(), + ComparisonUnitArray2 = null, + }; newSequence.Add(csDeleted); } else if (remainingInLeftParagraph == 0 && remainingInRightParagraph != 0) { var csInserted = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Inserted, - ComparisonUnitArray1 = null, - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 - .Skip(beforeCommonParagraphRight) - .Take(remainingInRightParagraph).ToArray() - }; + { + CorrelationStatus = CorrelationStatus.Inserted, + ComparisonUnitArray1 = null, + ComparisonUnitArray2 = unknown + .ComparisonUnitArray2.Skip(beforeCommonParagraphRight) + .Take(remainingInRightParagraph) + .ToArray(), + }; newSequence.Add(csInserted); } else if (remainingInLeftParagraph != 0 && remainingInRightParagraph != 0) { var csUnknown = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Unknown, - ComparisonUnitArray1 = unknown.ComparisonUnitArray1 - .Skip(beforeCommonParagraphLeft) - .Take(remainingInLeftParagraph).ToArray(), - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 - .Skip(beforeCommonParagraphRight) - .Take(remainingInRightParagraph).ToArray() - }; + { + CorrelationStatus = CorrelationStatus.Unknown, + ComparisonUnitArray1 = unknown + .ComparisonUnitArray1.Skip(beforeCommonParagraphLeft) + .Take(remainingInLeftParagraph) + .ToArray(), + ComparisonUnitArray2 = unknown + .ComparisonUnitArray2.Skip(beforeCommonParagraphRight) + .Take(remainingInRightParagraph) + .ToArray(), + }; newSequence.Add(csUnknown); } else if (remainingInLeftParagraph == 0 && remainingInRightParagraph == 0) @@ -2448,13 +2474,15 @@ private static List FindCommonAtBeginningAndEnd( } var csEqual = new CorrelatedSequence - { - CorrelationStatus = CorrelationStatus.Equal, - ComparisonUnitArray1 = unknown.ComparisonUnitArray1 - .Skip(unknown.ComparisonUnitArray1.Length - countCommonAtEnd).ToArray(), - ComparisonUnitArray2 = unknown.ComparisonUnitArray2 - .Skip(unknown.ComparisonUnitArray2.Length - countCommonAtEnd).ToArray() - }; + { + CorrelationStatus = CorrelationStatus.Equal, + ComparisonUnitArray1 = unknown + .ComparisonUnitArray1.Skip(unknown.ComparisonUnitArray1.Length - countCommonAtEnd) + .ToArray(), + ComparisonUnitArray2 = unknown + .ComparisonUnitArray2.Skip(unknown.ComparisonUnitArray2.Length - countCommonAtEnd) + .ToArray(), + }; newSequence.Add(csEqual); return newSequence; @@ -2576,27 +2604,20 @@ private static List SplitAtParagraphMark(ComparisonUnit[] cua) if (i == cua.Length) { - return new List - { - cua - }; + return new List { cua }; } - return new List - { - cua.Take(i).ToArray(), - cua.Skip(i).ToArray() - }; + return new List { cua.Take(i).ToArray(), cua.Skip(i).ToArray() }; } private static object CoalesceRecurse( OpenXmlPart part, IEnumerable list, int level, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { - var grouped = list - .GroupBy(ca => level >= ca.AncestorElements.Length ? "" : ca.AncestorUnids[level]) + var grouped = list.GroupBy(ca => level >= ca.AncestorElements.Length ? "" : ca.AncestorUnids[level]) .Where(g => g.Key != ""); // if there are no deeper children, then we're done. @@ -2627,12 +2648,10 @@ private static object CoalesceRecurse( var elementList = grouped .Select(g => { - var ancestorBeingConstructed = - g.First().AncestorElements[level]; // these will all be the same, by definition + var ancestorBeingConstructed = g.First().AncestorElements[level]; // these will all be the same, by definition // need to group by corr stat - var groupedChildren = g - .GroupAdjacent(gc => + var groupedChildren = g.GroupAdjacent(gc => { var key = ""; if (level < gc.AncestorElements.Length - 1) @@ -2671,10 +2690,12 @@ private static object CoalesceRecurse( }) .ToList(); - var newPara = new XElement(W.p, + var newPara = new XElement( + W.p, ancestorBeingConstructed.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt), new XAttribute(PtOpenXml.Unid, g.Key), - newChildElements); + newChildElements + ); return newPara; } @@ -2703,10 +2724,12 @@ private static object CoalesceRecurse( .ToList(); var rPr = ancestorBeingConstructed.Element(W.rPr); - var newRun = new XElement(W.r, + var newRun = new XElement( + W.r, ancestorBeingConstructed.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt), rPr, - newChildElements); + newChildElements + ); return newRun; } @@ -2719,19 +2742,22 @@ private static object CoalesceRecurse( var del = gc.First().CorrelationStatus == CorrelationStatus.Deleted; var ins = gc.First().CorrelationStatus == CorrelationStatus.Inserted; if (del) - return new XElement(W.delText, + return new XElement( + W.delText, new XAttribute(PtOpenXml.Status, "Deleted"), GetXmlSpaceAttribute(textOfTextElement), - textOfTextElement); + textOfTextElement + ); if (ins) - return new XElement(W.t, + return new XElement( + W.t, new XAttribute(PtOpenXml.Status, "Inserted"), GetXmlSpaceAttribute(textOfTextElement), - textOfTextElement); + textOfTextElement + ); - return (object) new XElement(W.t, - GetXmlSpaceAttribute(textOfTextElement), - textOfTextElement); + return (object) + new XElement(W.t, GetXmlSpaceAttribute(textOfTextElement), textOfTextElement); }) .ToList(); return newChildElements; @@ -2745,26 +2771,30 @@ private static object CoalesceRecurse( var del = gc.First().CorrelationStatus == CorrelationStatus.Deleted; if (del) { - return (object) gc.Select(gcc => - { - var newDrawing = new XElement(gcc.ContentElement); - newDrawing.Add(new XAttribute(PtOpenXml.Status, "Deleted")); - - var openXmlPartOfDeletedContent = gc.First().Part; - var openXmlPartInNewDocument = part; - return gc.Select(gce => + return (object) + gc.Select(gcc => { - var packageOfDeletedContent = openXmlPartOfDeletedContent.OpenXmlPackage.GetPackage(); - var packageOfNewContent = openXmlPartInNewDocument.OpenXmlPackage.GetPackage(); - var partInDeletedDocument = packageOfDeletedContent.GetPart(part.Uri); - var partInNewDocument = packageOfNewContent.GetPart(part.Uri); - - return MoveRelatedPartsToDestination( - partInDeletedDocument, - partInNewDocument, - newDrawing); + var newDrawing = new XElement(gcc.ContentElement); + newDrawing.Add(new XAttribute(PtOpenXml.Status, "Deleted")); + + var openXmlPartOfDeletedContent = gc.First().Part; + var openXmlPartInNewDocument = part; + return gc.Select(gce => + { + var packageOfDeletedContent = + openXmlPartOfDeletedContent.OpenXmlPackage.GetPackage(); + var packageOfNewContent = + openXmlPartInNewDocument.OpenXmlPackage.GetPackage(); + var partInDeletedDocument = packageOfDeletedContent.GetPart(part.Uri); + var partInNewDocument = packageOfNewContent.GetPart(part.Uri); + + return MoveRelatedPartsToDestination( + partInDeletedDocument, + partInNewDocument, + newDrawing + ); + }); }); - }); } var ins = gc.First().CorrelationStatus == CorrelationStatus.Inserted; @@ -2779,15 +2809,18 @@ private static object CoalesceRecurse( var openXmlPartInNewDocument = part; return gc.Select(gce => { - var packageOfSourceContent = openXmlPartOfInsertedContent.OpenXmlPackage.GetPackage(); - var packageOfNewContent = openXmlPartInNewDocument.OpenXmlPackage.GetPackage(); + var packageOfSourceContent = + openXmlPartOfInsertedContent.OpenXmlPackage.GetPackage(); + var packageOfNewContent = + openXmlPartInNewDocument.OpenXmlPackage.GetPackage(); var partInDeletedDocument = packageOfSourceContent.GetPart(part.Uri); var partInNewDocument = packageOfNewContent.GetPart(part.Uri); return MoveRelatedPartsToDestination( partInDeletedDocument, partInNewDocument, - newDrawing); + newDrawing + ); }); }); } @@ -2807,23 +2840,25 @@ private static object CoalesceRecurse( var del = gc.First().CorrelationStatus == CorrelationStatus.Deleted; if (del) { - return gc.Select(gcc => - new XElement(W.del, - new XAttribute(W.author, settings.AuthorForRevisions), - new XAttribute(W.id, s_maxId++), - new XAttribute(W.date, settings.DateTimeForRevisions), - gcc.ContentElement)); + return gc.Select(gcc => new XElement( + W.del, + new XAttribute(W.author, settings.AuthorForRevisions), + new XAttribute(W.id, s_maxId++), + new XAttribute(W.date, settings.DateTimeForRevisions), + gcc.ContentElement + )); } var ins = gc.First().CorrelationStatus == CorrelationStatus.Inserted; if (ins) { - return gc.Select(gcc => - new XElement(W.ins, - new XAttribute(W.author, settings.AuthorForRevisions), - new XAttribute(W.id, s_maxId++), - new XAttribute(W.date, settings.DateTimeForRevisions), - gcc.ContentElement)); + return gc.Select(gcc => new XElement( + W.ins, + new XAttribute(W.author, settings.AuthorForRevisions), + new XAttribute(W.id, s_maxId++), + new XAttribute(W.date, settings.DateTimeForRevisions), + gcc.ContentElement + )); } return gc.Select(gcc => gcc.ContentElement); @@ -2843,9 +2878,13 @@ private static object CoalesceRecurse( { return gc.Select(gcc => { - var dup = new XElement(ancestorBeingConstructed.Name, - ancestorBeingConstructed.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt), - new XAttribute(PtOpenXml.Status, "Deleted")); + var dup = new XElement( + ancestorBeingConstructed.Name, + ancestorBeingConstructed + .Attributes() + .Where(a => a.Name.Namespace != PtOpenXml.pt), + new XAttribute(PtOpenXml.Status, "Deleted") + ); return dup; }); } @@ -2854,9 +2893,13 @@ private static object CoalesceRecurse( { return gc.Select(gcc => { - var dup = new XElement(ancestorBeingConstructed.Name, - ancestorBeingConstructed.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt), - new XAttribute(PtOpenXml.Status, "Inserted")); + var dup = new XElement( + ancestorBeingConstructed.Name, + ancestorBeingConstructed + .Attributes() + .Where(a => a.Name.Namespace != PtOpenXml.pt), + new XAttribute(PtOpenXml.Status, "Inserted") + ); return dup; }); } @@ -2868,24 +2911,104 @@ private static object CoalesceRecurse( } if (ancestorBeingConstructed.Name == W.tbl) - return ReconstructElement(part, g, ancestorBeingConstructed, W.tblPr, W.tblGrid, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W.tblPr, + W.tblGrid, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == W.tr) - return ReconstructElement(part, g, ancestorBeingConstructed, W.trPr, null, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W.trPr, + null, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == W.tc) - return ReconstructElement(part, g, ancestorBeingConstructed, W.tcPr, null, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W.tcPr, + null, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == W.sdt) - return ReconstructElement(part, g, ancestorBeingConstructed, W.sdtPr, W.sdtEndPr, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W.sdtPr, + W.sdtEndPr, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == W.pict) - return ReconstructElement(part, g, ancestorBeingConstructed, VML.shapetype, null, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + VML.shapetype, + null, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == VML.shape) - return ReconstructElement(part, g, ancestorBeingConstructed, W10.wrap, null, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W10.wrap, + null, + null, + level, + settings + ); if (ancestorBeingConstructed.Name == W._object) - return ReconstructElement(part, g, ancestorBeingConstructed, VML.shapetype, VML.shape, O.OLEObject, level, - settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + VML.shapetype, + VML.shape, + O.OLEObject, + level, + settings + ); if (ancestorBeingConstructed.Name == W.ruby) - return ReconstructElement(part, g, ancestorBeingConstructed, W.rubyPr, null, null, level, settings); - - return (object) ReconstructElement(part, g, ancestorBeingConstructed, null, null, null, level, settings); + return ReconstructElement( + part, + g, + ancestorBeingConstructed, + W.rubyPr, + null, + null, + level, + settings + ); + + return (object)ReconstructElement( + part, + g, + ancestorBeingConstructed, + null, + null, + null, + level, + settings + ); }) .ToList(); return elementList; @@ -2899,7 +3022,8 @@ private static XElement ReconstructElement( XName props2XName, XName props3XName, int level, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var newChildElements = CoalesceRecurse(part, g, level + 1, settings); @@ -2915,9 +3039,14 @@ private static XElement ReconstructElement( if (props3XName != null) props3 = ancestorBeingConstructed.Elements(props3XName); - var reconstructedElement = new XElement(ancestorBeingConstructed.Name, + var reconstructedElement = new XElement( + ancestorBeingConstructed.Name, ancestorBeingConstructed.Attributes(), - props1, props2, props3, newChildElements); + props1, + props2, + props3, + newChildElements + ); return reconstructedElement; } @@ -2926,9 +3055,11 @@ private static void SetAfterUnids(CorrelatedSequence unknown) { if (unknown.ComparisonUnitArray1.Length == 1 && unknown.ComparisonUnitArray2.Length == 1) { - if (unknown.ComparisonUnitArray1[0] is ComparisonUnitGroup cua1 && - unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 && - cua1.ComparisonUnitGroupType == cua2.ComparisonUnitGroupType) + if ( + unknown.ComparisonUnitArray1[0] is ComparisonUnitGroup cua1 + && unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 + && cua1.ComparisonUnitGroupType == cua2.ComparisonUnitGroupType + ) { var groupType = cua1.ComparisonUnitGroupType; var da1 = cua1.DescendantContentAtoms(); @@ -2940,7 +3071,7 @@ unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 && ComparisonUnitGroupType.Row => W.tr, ComparisonUnitGroupType.Cell => W.tc, ComparisonUnitGroupType.Textbox => W.txbxContent, - _ => null + _ => null, }; if (takeThruName == null) @@ -2962,7 +3093,7 @@ unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 && var unidList = relevantAncestors .Select(a => { - var unid = (string) a.Attribute(PtOpenXml.Unid); + var unid = (string)a.Attribute(PtOpenXml.Unid); if (unid == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -2973,12 +3104,7 @@ unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 && foreach (var da in da2) { var ancestorsToSet = da.AncestorElements.Take(unidList.Length); - var zipped = ancestorsToSet.Zip(unidList, (a, u) => - new - { - Ancestor = a, - Unid = u - }); + var zipped = ancestorsToSet.Zip(unidList, (a, u) => new { Ancestor = a, Unid = u }); foreach (var z in zipped) { @@ -2997,18 +3123,31 @@ unknown.ComparisonUnitArray2[0] is ComparisonUnitGroup cua2 && } } - private static List ProcessCorrelatedHashes(CorrelatedSequence unknown, WmlComparerSettings settings) + private static List ProcessCorrelatedHashes( + CorrelatedSequence unknown, + WmlComparerSettings settings + ) { // never attempt this optimization if there are less than 3 groups var maxd = Math.Min(unknown.ComparisonUnitArray1.Length, unknown.ComparisonUnitArray2.Length); if (maxd < 3) return null; - if (unknown.ComparisonUnitArray1.FirstOrDefault() is ComparisonUnitGroup firstInCu1 && - unknown.ComparisonUnitArray2.FirstOrDefault() is ComparisonUnitGroup firstInCu2) - { - if (firstInCu1.ComparisonUnitGroupType is ComparisonUnitGroupType.Paragraph or ComparisonUnitGroupType.Table or ComparisonUnitGroupType.Row && - firstInCu2.ComparisonUnitGroupType is ComparisonUnitGroupType.Paragraph or ComparisonUnitGroupType.Table or ComparisonUnitGroupType.Row) + if ( + unknown.ComparisonUnitArray1.FirstOrDefault() is ComparisonUnitGroup firstInCu1 + && unknown.ComparisonUnitArray2.FirstOrDefault() is ComparisonUnitGroup firstInCu2 + ) + { + if ( + firstInCu1.ComparisonUnitGroupType + is ComparisonUnitGroupType.Paragraph + or ComparisonUnitGroupType.Table + or ComparisonUnitGroupType.Row + && firstInCu2.ComparisonUnitGroupType + is ComparisonUnitGroupType.Paragraph + or ComparisonUnitGroupType.Table + or ComparisonUnitGroupType.Row + ) { var groupType = firstInCu1.ComparisonUnitGroupType; @@ -3036,12 +3175,13 @@ private static List ProcessCorrelatedHashes(CorrelatedSequen var thisI2 = i2; while (true) { - var match = cul1[thisI1] is ComparisonUnitGroup group1 && - cul2[thisI2] is ComparisonUnitGroup group2 && - group1.ComparisonUnitGroupType == group2.ComparisonUnitGroupType && - group1.CorrelatedSHA1Hash != null && - group2.CorrelatedSHA1Hash != null && - group1.CorrelatedSHA1Hash == group2.CorrelatedSHA1Hash; + var match = + cul1[thisI1] is ComparisonUnitGroup group1 + && cul2[thisI2] is ComparisonUnitGroup group2 + && group1.ComparisonUnitGroupType == group2.ComparisonUnitGroupType + && group1.CorrelatedSHA1Hash != null + && group2.CorrelatedSHA1Hash != null + && group1.CorrelatedSHA1Hash == group2.CorrelatedSHA1Hash; if (match) { @@ -3093,15 +3233,13 @@ cul2[thisI2] is ComparisonUnitGroup group2 && else if (currentLongestCommonSequenceLength > 1 && currentLongestCommonSequenceLength <= 3) { var numberOfAtoms1 = unknown - .ComparisonUnitArray1 - .Skip(currentI1) + .ComparisonUnitArray1.Skip(currentI1) .Take(currentLongestCommonSequenceLength) .Select(z => z.DescendantContentAtoms().Count()) .Sum(); var numberOfAtoms2 = unknown - .ComparisonUnitArray2 - .Skip(currentI2) + .ComparisonUnitArray2.Skip(currentI2) .Take(currentLongestCommonSequenceLength) .Select(z => z.DescendantContentAtoms().Count()) .Sum(); @@ -3126,7 +3264,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = cul1.Take(currentI1).ToArray(), - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -3136,7 +3274,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = cul2.Take(currentI2).ToArray() + ComparisonUnitArray2 = cul2.Take(currentI2).ToArray(), }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -3146,7 +3284,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = cul1.Take(currentI1).ToArray(), - ComparisonUnitArray2 = cul2.Take(currentI2).ToArray() + ComparisonUnitArray2 = cul2.Take(currentI2).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); } @@ -3160,16 +3298,8 @@ cul2[thisI2] is ComparisonUnitGroup group2 && var unknownCorrelatedSequence = new CorrelatedSequence { CorrelationStatus = CorrelationStatus.Unknown, - ComparisonUnitArray1 = cul1 - .Skip(currentI1) - .Skip(i) - .Take(1) - .ToArray(), - ComparisonUnitArray2 = cul2 - .Skip(currentI2) - .Skip(i) - .Take(1) - .ToArray() + ComparisonUnitArray1 = cul1.Skip(currentI1).Skip(i).Take(1).ToArray(), + ComparisonUnitArray2 = cul2.Skip(currentI2).Skip(i).Take(1).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); } @@ -3183,7 +3313,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Deleted, ComparisonUnitArray1 = cul1.Skip(endI1).ToArray(), - ComparisonUnitArray2 = null + ComparisonUnitArray2 = null, }; newListOfCorrelatedSequence.Add(deletedCorrelatedSequence); } @@ -3193,7 +3323,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Inserted, ComparisonUnitArray1 = null, - ComparisonUnitArray2 = cul2.Skip(endI2).ToArray() + ComparisonUnitArray2 = cul2.Skip(endI2).ToArray(), }; newListOfCorrelatedSequence.Add(insertedCorrelatedSequence); } @@ -3203,7 +3333,7 @@ cul2[thisI2] is ComparisonUnitGroup group2 && { CorrelationStatus = CorrelationStatus.Unknown, ComparisonUnitArray1 = cul1.Skip(endI1).ToArray(), - ComparisonUnitArray2 = cul2.Skip(endI2).ToArray() + ComparisonUnitArray2 = cul2.Skip(endI2).ToArray(), }; newListOfCorrelatedSequence.Add(unknownCorrelatedSequence); } diff --git a/Clippit/Comparer/WmlComparer.Private.Methods.Util.cs b/Clippit/Comparer/WmlComparer.Private.Methods.Util.cs index 22fa9349..00badb77 100644 --- a/Clippit/Comparer/WmlComparer.Private.Methods.Util.cs +++ b/Clippit/Comparer/WmlComparer.Private.Methods.Util.cs @@ -16,7 +16,8 @@ public static partial class WmlComparer private static XElement MoveRelatedPartsToDestination( IPackagePart partOfDeletedContent, IPackagePart partInNewDocument, - XElement contentElement) + XElement contentElement + ) { var elementsToUpdate = contentElement .Descendants() @@ -32,14 +33,14 @@ private static XElement MoveRelatedPartsToDestination( foreach (var att in attributesToUpdate) { - var rId = (string) att; + var rId = (string)att; var relationshipForDeletedPart = partOfDeletedContent.Relationships[rId]; - var targetUri = PackUriHelper - .ResolvePartUri( - new Uri(partOfDeletedContent.Uri.ToString(), UriKind.Relative), - relationshipForDeletedPart.TargetUri); + var targetUri = PackUriHelper.ResolvePartUri( + new Uri(partOfDeletedContent.Uri.ToString(), UriKind.Relative), + relationshipForDeletedPart.TargetUri + ); var relatedPackagePart = partOfDeletedContent.Package.GetPart(targetUri); var uriSplit = relatedPackagePart.Uri.ToString().Split('/'); @@ -47,20 +48,30 @@ private static XElement MoveRelatedPartsToDestination( string uriString; if (last.Length == 2) { - uriString = uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() + - "P" + Guid.NewGuid().ToString().Replace("-", "") + "." + last[1]; + uriString = + uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() + + "P" + + Guid.NewGuid().ToString().Replace("-", "") + + "." + + last[1]; } else { - uriString = uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() + - "P" + Guid.NewGuid().ToString().Replace("-", ""); + uriString = + uriSplit.SkipLast(1).Select(p => p + "/").StringConcatenate() + + "P" + + Guid.NewGuid().ToString().Replace("-", ""); } var uri = relatedPackagePart.Uri.IsAbsoluteUri ? new Uri(uriString, UriKind.Absolute) : new Uri(uriString, UriKind.Relative); - var newPart = partInNewDocument.Package.CreatePart(uri, relatedPackagePart.ContentType, CompressionOption.Normal); + var newPart = partInNewDocument.Package.CreatePart( + uri, + relatedPackagePart.ContentType, + CompressionOption.Normal + ); // ReSharper disable once PossibleNullReferenceException using (var oldPartStream = relatedPackagePart.GetStream(FileMode.Open, FileAccess.Read)) @@ -70,8 +81,12 @@ private static XElement MoveRelatedPartsToDestination( } var newRid = Relationships.GetNewRelationshipId(); - partInNewDocument.Relationships.Create(newPart.Uri, TargetMode.Internal, - relationshipForDeletedPart.RelationshipType, newRid); + partInNewDocument.Relationships.Create( + newPart.Uri, + TargetMode.Internal, + relationshipForDeletedPart.RelationshipType, + newRid + ); att.Value = newRid; if (newPart.ContentType.EndsWith("xml")) @@ -94,8 +109,10 @@ private static XElement MoveRelatedPartsToDestination( private static XAttribute GetXmlSpaceAttribute(string textOfTextElement) { - if (char.IsWhiteSpace(textOfTextElement[0]) || - char.IsWhiteSpace(textOfTextElement[textOfTextElement.Length - 1])) + if ( + char.IsWhiteSpace(textOfTextElement[0]) + || char.IsWhiteSpace(textOfTextElement[textOfTextElement.Length - 1]) + ) return new XAttribute(XNamespace.Xml + "space", "preserve"); return null; diff --git a/Clippit/Comparer/WmlComparer.Private.NestedTypes.cs b/Clippit/Comparer/WmlComparer.Private.NestedTypes.cs index 56447bae..d75a2670 100644 --- a/Clippit/Comparer/WmlComparer.Private.NestedTypes.cs +++ b/Clippit/Comparer/WmlComparer.Private.NestedTypes.cs @@ -24,7 +24,7 @@ private class ConsolidationInfo public string RevisionHash { get; set; } public XElement[] Footnotes { get; set; } public XElement[] Endnotes { get; set; } - public string RevisionString { get; set; }// for debugging purposes only + public string RevisionString { get; set; } // for debugging purposes only } private class RecursionInfo diff --git a/Clippit/Comparer/WmlComparer.Public.Methods.Compare.cs b/Clippit/Comparer/WmlComparer.Public.Methods.Compare.cs index 7e8c93a8..1a7d78d6 100644 --- a/Clippit/Comparer/WmlComparer.Public.Methods.Compare.cs +++ b/Clippit/Comparer/WmlComparer.Public.Methods.Compare.cs @@ -54,7 +54,8 @@ private static WmlDocument CompareInternal( WmlDocument source1, WmlDocument source2, WmlComparerSettings settings, - bool preProcessMarkupInOriginal) + bool preProcessMarkupInOriginal + ) { if (preProcessMarkupInOriginal) { @@ -170,16 +171,32 @@ private static void SaveDocumentIfDesired(WmlDocument source, string name, WmlCo } } - private static void SaveDocumentsAfterProducingDocument(MemoryStream ms1, MemoryStream ms2, WmlComparerSettings settings) + private static void SaveDocumentsAfterProducingDocument( + MemoryStream ms1, + MemoryStream ms2, + WmlComparerSettings settings + ) { if (SaveIntermediateFilesForDebugging && settings.DebugTempFileDi != null) { - SaveDocumentIfDesired(new WmlDocument("after1.docx", ms1), "Source1-Step5-AfterProducingDocument.docx", settings); - SaveDocumentIfDesired(new WmlDocument("after2.docx", ms2), "Source2-Step5-AfterProducingDocument.docx", settings); + SaveDocumentIfDesired( + new WmlDocument("after1.docx", ms1), + "Source1-Step5-AfterProducingDocument.docx", + settings + ); + SaveDocumentIfDesired( + new WmlDocument("after2.docx", ms2), + "Source2-Step5-AfterProducingDocument.docx", + settings + ); } } - private static void SaveCleanedDocuments(WmlDocument source1, WmlDocument producedDocument, WmlComparerSettings settings) + private static void SaveCleanedDocuments( + WmlDocument source1, + WmlDocument producedDocument, + WmlComparerSettings settings + ) { if (SaveIntermediateFilesForDebugging && settings.DebugTempFileDi != null) { @@ -214,10 +231,13 @@ private static object CleanPartTransform(XNode node) { if (node is XElement element) { - return new XElement(element.Name, - element.Attributes().Where(a => a.Name.Namespace != PtOpenXml.pt && - !a.Name.LocalName.ToLower().Contains("rsid")), - element.Nodes().Select(CleanPartTransform)); + return new XElement( + element.Name, + element + .Attributes() + .Where(a => a.Name.Namespace != PtOpenXml.pt && !a.Name.LocalName.ToLower().Contains("rsid")), + element.Nodes().Select(CleanPartTransform) + ); } return node; diff --git a/Clippit/Comparer/WmlComparer.Public.Methods.Consolidate.cs b/Clippit/Comparer/WmlComparer.Public.Methods.Consolidate.cs index 0a81f447..5f2448ca 100644 --- a/Clippit/Comparer/WmlComparer.Public.Methods.Consolidate.cs +++ b/Clippit/Comparer/WmlComparer.Public.Methods.Consolidate.cs @@ -25,7 +25,8 @@ public static partial class WmlComparer public static WmlDocument Consolidate( WmlDocument original, List revisedDocumentInfoList, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var consolidateSettings = new WmlComparerConsolidateSettings(); return Consolidate(original, revisedDocumentInfoList, settings, consolidateSettings); @@ -35,7 +36,8 @@ public static WmlDocument Consolidate( WmlDocument original, List revisedDocumentInfoList, WmlComparerSettings settings, - WmlComparerConsolidateSettings consolidateSettings) + WmlComparerConsolidateSettings consolidateSettings + ) { // pre-process the original, so that it already has unids for all elements // then when comparing all documents to the original, each one will have the unid as appropriate @@ -72,27 +74,25 @@ public static WmlDocument Consolidate( var consolidatedMainDocPartRoot = consolidatedMainDocPartXDoc.Root ?? throw new ArgumentException(); // save away last sectPr - var savedSectPr = consolidatedMainDocPartRoot - .Elements(W.body) - .Elements(W.sectPr) - .LastOrDefault(); + var savedSectPr = consolidatedMainDocPartRoot.Elements(W.body).Elements(W.sectPr).LastOrDefault(); - consolidatedMainDocPartRoot - .Elements(W.body) - .Elements(W.sectPr) - .Remove(); + consolidatedMainDocPartRoot.Elements(W.body).Elements(W.sectPr).Remove(); var consolidatedByUnid = consolidatedMainDocPartXDoc .Descendants() .Where(d => (d.Name == W.p || d.Name == W.tbl) && d.Attribute(PtOpenXml.Unid) != null) - .ToDictionary(d => (string) d.Attribute(PtOpenXml.Unid)); + .ToDictionary(d => (string)d.Attribute(PtOpenXml.Unid)); var deltaNbr = 1; foreach (var revisedDocumentInfo in revisedDocumentInfoList) { settings.StartingIdForFootnotesEndnotes = deltaNbr * 2000 + 3000; - var delta = CompareInternal(originalWithUnids, revisedDocumentInfo.RevisedDocument, settings, - false); + var delta = CompareInternal( + originalWithUnids, + revisedDocumentInfo.RevisedDocument, + settings, + false + ); if (SaveIntermediateFilesForDebugging && settings.DebugTempFileDi != null) { @@ -106,7 +106,8 @@ public static WmlDocument Consolidate( msOriginalWithUnids.Write( originalWithUnids.DocumentByteArray, 0, - originalWithUnids.DocumentByteArray.Length); + originalWithUnids.DocumentByteArray.Length + ); msDelta.Write(delta.DocumentByteArray, 0, delta.DocumentByteArray.Length); @@ -115,11 +116,12 @@ public static WmlDocument Consolidate( var modMainDocPart = wDocDelta.MainDocumentPart; var modMainDocPartXDoc = modMainDocPart.GetXDocument(); var blockLevelContentToMove = modMainDocPartXDoc - .Root - .DescendantsTrimmed(d => d.Name == W.txbxContent || d.Name == W.tr) + .Root.DescendantsTrimmed(d => d.Name == W.txbxContent || d.Name == W.tr) .Where(d => d.Name == W.p || d.Name == W.tbl) - .Where(d => d.Descendants().Any(z => z.Name == W.ins || z.Name == W.del) || - ContentContainsFootnoteEndnoteReferencesThatHaveRevisions(d, wDocDelta)) + .Where(d => + d.Descendants().Any(z => z.Name == W.ins || z.Name == W.del) + || ContentContainsFootnoteEndnoteReferencesThatHaveRevisions(d, wDocDelta) + ) .ToList(); foreach (var revision in blockLevelContentToMove) @@ -127,7 +129,7 @@ public static WmlDocument Consolidate( var elementLookingAt = revision; while (true) { - var unid = (string) elementLookingAt.Attribute(PtOpenXml.Unid); + var unid = (string)elementLookingAt.Attribute(PtOpenXml.Unid); if (unid == null) throw new OpenXmlPowerToolsException("Internal error"); @@ -145,10 +147,11 @@ public static WmlDocument Consolidate( .Descendants(W.footnoteReference) .Select(fr => { - var id = (int) fr.Attribute(W.id); + var id = (int)fr.Attribute(W.id); var fnXDoc = wDocDelta.MainDocumentPart.FootnotesPart.GetXDocument(); - var footnote = fnXDoc.Root.Elements(W.footnote) - .FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var footnote = fnXDoc + .Root.Elements(W.footnote) + .FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (footnote == null) throw new OpenXmlPowerToolsException("Internal Error"); @@ -159,22 +162,18 @@ public static WmlDocument Consolidate( .Descendants(W.endnoteReference) .Select(er => { - var id = (int) er.Attribute(W.id); + var id = (int)er.Attribute(W.id); var enXDoc = wDocDelta.MainDocumentPart.EndnotesPart.GetXDocument(); - var endnote = enXDoc.Root.Elements(W.endnote) - .FirstOrDefault(en => (int) en.Attribute(W.id) == id); + var endnote = enXDoc + .Root.Elements(W.endnote) + .FirstOrDefault(en => (int)en.Attribute(W.id) == id); if (endnote == null) throw new OpenXmlPowerToolsException("Internal Error"); return endnote; }) .ToArray(); - AddToAnnotation( - wDocDelta, - consolidatedWDoc, - elementToInsertAfter, - ci, - settings); + AddToAnnotation(wDocDelta, consolidatedWDoc, elementToInsertAfter, ci, settings); break; } @@ -185,8 +184,7 @@ public static WmlDocument Consolidate( if (elementBeforeRevision == null) { var firstElement = consolidatedMainDocPartXDoc - .Root - .Element(W.body) + .Root.Element(W.body) .Elements() .FirstOrDefault(e => e.Name == W.p || e.Name == W.tbl); @@ -199,10 +197,11 @@ public static WmlDocument Consolidate( .Descendants(W.footnoteReference) .Select(fr => { - var id = (int) fr.Attribute(W.id); + var id = (int)fr.Attribute(W.id); var fnXDoc = wDocDelta.MainDocumentPart.FootnotesPart.GetXDocument(); - var footnote = fnXDoc.Root.Elements(W.footnote) - .FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var footnote = fnXDoc + .Root.Elements(W.footnote) + .FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (footnote == null) throw new OpenXmlPowerToolsException("Internal Error"); @@ -213,22 +212,18 @@ public static WmlDocument Consolidate( .Descendants(W.endnoteReference) .Select(er => { - var id = (int) er.Attribute(W.id); + var id = (int)er.Attribute(W.id); var enXDoc = wDocDelta.MainDocumentPart.EndnotesPart.GetXDocument(); - var endnote = enXDoc.Root.Elements(W.endnote) - .FirstOrDefault(en => (int) en.Attribute(W.id) == id); + var endnote = enXDoc + .Root.Elements(W.endnote) + .FirstOrDefault(en => (int)en.Attribute(W.id) == id); if (endnote == null) throw new OpenXmlPowerToolsException("Internal Error"); return endnote; }) .ToArray(); - AddToAnnotation( - wDocDelta, - consolidatedWDoc, - firstElement, - ci, - settings); + AddToAnnotation(wDocDelta, consolidatedWDoc, firstElement, ci, settings); break; } @@ -242,28 +237,40 @@ public static WmlDocument Consolidate( // at this point, everything is added as an annotation, from all documents to be merged. // so now the process is to go through and add the annotations to the document var elementsToProcess = consolidatedMainDocPartXDoc - .Root - .Descendants() + .Root.Descendants() .Where(d => d.Annotation>() != null) .ToList(); - var emptyParagraph = new XElement(W.p, - new XElement(W.pPr, - new XElement(W.spacing, + var emptyParagraph = new XElement( + W.p, + new XElement( + W.pPr, + new XElement( + W.spacing, new XAttribute(W.after, "0"), new XAttribute(W.line, "240"), - new XAttribute(W.lineRule, "auto")))); + new XAttribute(W.lineRule, "auto") + ) + ) + ); foreach (var ele in elementsToProcess) { var lci = ele.Annotation>(); // process before - var contentToAddBefore = lci - .Where(ci => ci.InsertBefore) + var contentToAddBefore = lci.Where(ci => ci.InsertBefore) .GroupAdjacent(ci => ci.Revisor + ci.Color) - .Select((groupedCi, idx) => AssembledConjoinedRevisionContent(emptyParagraph, groupedCi, idx, - consolidatedWDoc, consolidateSettings)); + .Select( + (groupedCi, idx) => + AssembledConjoinedRevisionContent( + emptyParagraph, + groupedCi, + idx, + consolidatedWDoc, + consolidateSettings + ) + ); ele.AddBeforeSelf(contentToAddBefore); // process after @@ -278,16 +285,23 @@ public static WmlDocument Consolidate( ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This is the code that determines if revisions should be consolidated into one. - var uniqueRevisions = lci - .Where(ci => ci.InsertBefore == false) + var uniqueRevisions = lci.Where(ci => ci.InsertBefore == false) .GroupBy(ci => { // Get a hash after first accepting revisions and compressing the text. - var acceptedRevisionElement = - RevisionProcessor.AcceptRevisionsForElement(ci.RevisionElement); - var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(acceptedRevisionElement.Value - .Replace(" ", "").Replace(" ", "").Replace(" ", "").Replace("\n", "").Replace(".", "") - .Replace(",", "").ToUpper()); + var acceptedRevisionElement = RevisionProcessor.AcceptRevisionsForElement( + ci.RevisionElement + ); + var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String( + acceptedRevisionElement + .Value.Replace(" ", "") + .Replace(" ", "") + .Replace(" ", "") + .Replace("\n", "") + .Replace(".", "") + .Replace(",", "") + .ToUpper() + ); return sha1Hash; }) .OrderByDescending(g => g.Count()) @@ -321,15 +335,19 @@ public static WmlDocument Consolidate( { var sb = new StringBuilder(); sb.Append( - "====================================================================================================" + - NewLine); + "====================================================================================================" + + NewLine + ); sb.Append("Non-Consolidated Revision" + NewLine); sb.Append( - "====================================================================================================" + - NewLine); + "====================================================================================================" + + NewLine + ); foreach (var urList in uniqueRevisions) { - var revisorList = urList.Select(ur => ur.Revisor + " : ").StringConcatenate() + var revisorList = urList + .Select(ur => ur.Revisor + " : ") + .StringConcatenate() .TrimEnd(' ', ':'); sb.Append("Revisors: " + revisorList + NewLine); var str = RevisionToLogFormTransform(urList.First().RevisionElement, 0, false); @@ -342,11 +360,18 @@ public static WmlDocument Consolidate( } } - var contentToAddAfter = lci - .Where(ci => ci.InsertBefore == false) + var contentToAddAfter = lci.Where(ci => ci.InsertBefore == false) .GroupAdjacent(ci => ci.Revisor + ci.Color) - .Select((groupedCi, idx) => AssembledConjoinedRevisionContent(emptyParagraph, groupedCi, idx, - consolidatedWDoc, consolidateSettings)); + .Select( + (groupedCi, idx) => + AssembledConjoinedRevisionContent( + emptyParagraph, + groupedCi, + idx, + consolidatedWDoc, + consolidateSettings + ) + ); ele.AddAfterSelf(contentToAddAfter); } @@ -443,10 +468,7 @@ public static WmlDocument Consolidate( } #endif - consolidatedMainDocPartXDoc - .Root? - .Element(W.body)? - .Add(savedSectPr); + consolidatedMainDocPartXDoc.Root?.Element(W.body)?.Add(savedSectPr); AddTableGridStyleToStylesPart(consolidatedWDoc.MainDocumentPart.StyleDefinitionsPart); FixUpRevisionIds(consolidatedWDoc, consolidatedMainDocPartXDoc); @@ -466,18 +488,25 @@ public static WmlDocument Consolidate( private static void MoveFootnotesEndnotesForConsolidatedRevisions( ConsolidationInfo ci, - WordprocessingDocument wDocConsolidated) + WordprocessingDocument wDocConsolidated + ) { var consolidatedFootnoteXDoc = wDocConsolidated.MainDocumentPart.FootnotesPart.GetXDocument(); var consolidatedEndnoteXDoc = wDocConsolidated.MainDocumentPart.EndnotesPart.GetXDocument(); var maxFootnoteId = 1; if (consolidatedFootnoteXDoc.Root?.Elements(W.footnote).Any() == true) - maxFootnoteId = consolidatedFootnoteXDoc.Root.Elements(W.footnote).Select(e => (int) e.Attribute(W.id)).Max(); + maxFootnoteId = consolidatedFootnoteXDoc + .Root.Elements(W.footnote) + .Select(e => (int)e.Attribute(W.id)) + .Max(); var maxEndnoteId = 1; if (consolidatedEndnoteXDoc.Root?.Elements(W.endnote).Any() == true) - maxEndnoteId = consolidatedEndnoteXDoc.Root.Elements(W.endnote).Select(e => (int) e.Attribute(W.id)).Max(); + maxEndnoteId = consolidatedEndnoteXDoc + .Root.Elements(W.endnote) + .Select(e => (int)e.Attribute(W.id)) + .Max(); // At this point, content might contain a footnote or endnote reference. // Need to add the footnote / endnote into the consolidated document (with the same guid id) @@ -488,8 +517,8 @@ private static void MoveFootnotesEndnotesForConsolidatedRevisions( var footnoteXDoc = wDocConsolidated.MainDocumentPart.FootnotesPart.GetXDocument(); foreach (var footnoteReference in ci.RevisionElement.Descendants(W.footnoteReference)) { - var id = (int) footnoteReference.Attribute(W.id); - var footnote = ci.Footnotes.FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var id = (int)footnoteReference.Attribute(W.id); + var footnote = ci.Footnotes.FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (footnote != null) { var newId = ++maxFootnoteId; @@ -509,8 +538,8 @@ private static void MoveFootnotesEndnotesForConsolidatedRevisions( var endnoteXDoc = wDocConsolidated.MainDocumentPart.EndnotesPart.GetXDocument(); foreach (var endnoteReference in ci.RevisionElement.Descendants(W.endnoteReference)) { - var id = (int) endnoteReference.Attribute(W.id); - var endnote = ci.Endnotes.FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var id = (int)endnoteReference.Attribute(W.id); + var endnote = ci.Endnotes.FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (endnote != null) { var newId = ++maxEndnoteId; @@ -529,8 +558,7 @@ private static void MoveFootnotesEndnotesForConsolidatedRevisions( private static void FixUpGroupIds(WordprocessingDocument wDoc) { var elementToFind = VML.@group; - var groupIdsToChange = wDoc - .ContentParts() + var groupIdsToChange = wDoc.ContentParts() .Select(cp => cp.GetXDocument()) .Select(xd => xd.Descendants().Where(d => d.Name == elementToFind)) .SelectMany(m => m); @@ -550,7 +578,8 @@ private static void FixUpGroupIds(WordprocessingDocument wDoc) private static bool ContentContainsFootnoteEndnoteReferencesThatHaveRevisions( XElement element, - WordprocessingDocument wDocDelta) + WordprocessingDocument wDocDelta + ) { IEnumerable footnoteEndnoteReferences = element .Descendants() @@ -568,11 +597,8 @@ private static bool ContentContainsFootnoteEndnoteReferencesThatHaveRevisions( XElement fnen; if (note.Name == W.footnoteReference) { - var id = (int) note.Attribute(W.id); - fnen = footnoteXDoc - .Root? - .Elements(W.footnote) - .FirstOrDefault(n => (int) n.Attribute(W.id) == id); + var id = (int)note.Attribute(W.id); + fnen = footnoteXDoc.Root?.Elements(W.footnote).FirstOrDefault(n => (int)n.Attribute(W.id) == id); if (fnen?.Descendants().Any(d => d.Name == W.ins || d.Name == W.del) == true) return true; @@ -580,11 +606,8 @@ private static bool ContentContainsFootnoteEndnoteReferencesThatHaveRevisions( if (note.Name == W.endnoteReference) { - var id = (int) note.Attribute(W.id); - fnen = endnoteXDoc - .Root? - .Elements(W.endnote) - .FirstOrDefault(n => (int) n.Attribute(W.id) == id); + var id = (int)note.Attribute(W.id); + fnen = endnoteXDoc.Root?.Elements(W.endnote).FirstOrDefault(n => (int)n.Attribute(W.id) == id); if (fnen?.Descendants().Any(d => d.Name == W.ins || d.Name == W.del) == true) return true; @@ -597,23 +620,30 @@ private static bool ContentContainsFootnoteEndnoteReferencesThatHaveRevisions( private static string RevisionToLogFormTransform(XElement element, int depth, bool inserting) { if (element.Name == W.p) - return "Paragraph" + NewLine + element.Elements().Select(e => RevisionToLogFormTransform(e, depth + 2, false)) - .StringConcatenate(); + return "Paragraph" + + NewLine + + element + .Elements() + .Select(e => RevisionToLogFormTransform(e, depth + 2, false)) + .StringConcatenate(); if (element.Name == W.pPr || element.Name == W.rPr) return ""; if (element.Name == W.r) - return element.Elements().Select(e => RevisionToLogFormTransform(e, depth, inserting)).StringConcatenate(); + return element + .Elements() + .Select(e => RevisionToLogFormTransform(e, depth, inserting)) + .StringConcatenate(); if (element.Name == W.t) { if (inserting) - return "".PadRight(depth) + "Inserted Text:" + QuoteIt((string) element) + NewLine; + return "".PadRight(depth) + "Inserted Text:" + QuoteIt((string)element) + NewLine; - return "".PadRight(depth) + "Text:" + QuoteIt((string) element) + NewLine; + return "".PadRight(depth) + "Text:" + QuoteIt((string)element) + NewLine; } if (element.Name == W.delText) - return "".PadRight(depth) + "Deleted Text:" + QuoteIt((string) element) + NewLine; + return "".PadRight(depth) + "Deleted Text:" + QuoteIt((string)element) + NewLine; if (element.Name == W.ins) return element.Elements().Select(e => RevisionToLogFormTransform(e, depth, true)).StringConcatenate(); if (element.Name == W.del) @@ -659,7 +689,8 @@ private static XElement[] AssembledConjoinedRevisionContent( IGrouping groupedCi, int idx, WordprocessingDocument wDocConsolidated, - WmlComparerConsolidateSettings consolidateSettings) + WmlComparerConsolidateSettings consolidateSettings + ) { var consolidatedFootnoteXDoc = wDocConsolidated.MainDocumentPart.FootnotesPart.GetXDocument(); var consolidatedEndnoteXDoc = wDocConsolidated.MainDocumentPart.EndnotesPart.GetXDocument(); @@ -667,28 +698,36 @@ private static XElement[] AssembledConjoinedRevisionContent( var maxFootnoteId = 1; if (consolidatedFootnoteXDoc.Root?.Elements(W.footnote).Any() == true) { - maxFootnoteId = consolidatedFootnoteXDoc.Root.Elements(W.footnote).Select(e => (int) e.Attribute(W.id)).Max(); + maxFootnoteId = consolidatedFootnoteXDoc + .Root.Elements(W.footnote) + .Select(e => (int)e.Attribute(W.id)) + .Max(); } var maxEndnoteId = 1; if (consolidatedEndnoteXDoc.Root?.Elements(W.endnote).Any() == true) { - maxEndnoteId = consolidatedEndnoteXDoc.Root.Elements(W.endnote).Select(e => (int) e.Attribute(W.id)).Max(); + maxEndnoteId = consolidatedEndnoteXDoc + .Root.Elements(W.endnote) + .Select(e => (int)e.Attribute(W.id)) + .Max(); } var revisor = groupedCi.First().Revisor; - var captionParagraph = new XElement(W.p, - new XElement(W.pPr, + var captionParagraph = new XElement( + W.p, + new XElement( + W.pPr, new XElement(W.jc, new XAttribute(W.val, "both")), - new XElement(W.rPr, - new XElement(W.b), - new XElement(W.bCs))), - new XElement(W.r, - new XElement(W.rPr, - new XElement(W.b), - new XElement(W.bCs)), - new XElement(W.t, revisor))); + new XElement(W.rPr, new XElement(W.b), new XElement(W.bCs)) + ), + new XElement( + W.r, + new XElement(W.rPr, new XElement(W.b), new XElement(W.bCs)), + new XElement(W.t, revisor) + ) + ); var colorRgb = groupedCi.First().Color.ToArgb(); var colorString = colorRgb.ToString("X"); @@ -699,43 +738,49 @@ private static XElement[] AssembledConjoinedRevisionContent( if (consolidateSettings.ConsolidateWithTable) { - var table = new XElement(W.tbl, - new XElement(W.tblPr, + var table = new XElement( + W.tbl, + new XElement( + W.tblPr, new XElement(W.tblStyle, new XAttribute(W.val, "TableGridForRevisions")), - new XElement(W.tblW, - new XAttribute(W._w, "0"), - new XAttribute(W.type, "auto")), - new XElement(W.shd, + new XElement(W.tblW, new XAttribute(W._w, "0"), new XAttribute(W.type, "auto")), + new XElement( + W.shd, new XAttribute(W.val, "clear"), new XAttribute(W.color, "auto"), - new XAttribute(W.fill, colorString)), - new XElement(W.tblLook, + new XAttribute(W.fill, colorString) + ), + new XElement( + W.tblLook, new XAttribute(W.firstRow, "0"), new XAttribute(W.lastRow, "0"), new XAttribute(W.firstColumn, "0"), new XAttribute(W.lastColumn, "0"), new XAttribute(W.noHBand, "0"), - new XAttribute(W.noVBand, "0"))), - new XElement(W.tblGrid, - new XElement(W.gridCol, new XAttribute(W._w, "9576"))), - new XElement(W.tr, - new XElement(W.tc, - new XElement(W.tcPr, - new XElement(W.shd, + new XAttribute(W.noVBand, "0") + ) + ), + new XElement(W.tblGrid, new XElement(W.gridCol, new XAttribute(W._w, "9576"))), + new XElement( + W.tr, + new XElement( + W.tc, + new XElement( + W.tcPr, + new XElement( + W.shd, new XAttribute(W.val, "clear"), new XAttribute(W.color, "auto"), - new XAttribute(W.fill, colorString))), + new XAttribute(W.fill, colorString) + ) + ), captionParagraph, groupedCi.Select(ci => { XElement paraAfter = null; if (ci.RevisionElement.Name == W.tbl) paraAfter = emptyParagraph; - XElement[] revisionInTable = - { - ci.RevisionElement, - paraAfter - }; + XElement[] revisionInTable = { ci.RevisionElement, paraAfter }; // At this point, content might contain a footnote or endnote reference. // Need to add the footnote / endnote into the consolidated document (with the same @@ -746,7 +791,10 @@ private static XElement[] AssembledConjoinedRevisionContent( AddEndnotes(ci, wDocConsolidated, ref maxEndnoteId); return revisionInTable; - })))); + }) + ) + ) + ); // if the last paragraph has a deleted paragraph mark, then remove the deletion from the paragraph mark. // This is to prevent Word from misbehaving. the last paragraph in a cell must not have a deleted @@ -756,28 +804,15 @@ private static XElement[] AssembledConjoinedRevisionContent( if (lastPara != null) { - var isDeleted = lastPara - .Elements(W.pPr) - .Elements(W.rPr) - .Elements(W.del) - .Any(); + var isDeleted = lastPara.Elements(W.pPr).Elements(W.rPr).Elements(W.del).Any(); if (isDeleted) { - lastPara - .Elements(W.pPr) - .Elements(W.rPr) - .Elements(W.del) - .Remove(); + lastPara.Elements(W.pPr).Elements(W.rPr).Elements(W.del).Remove(); } } - XElement[] content = - { - idx == 0 ? emptyParagraph : null, - table, - emptyParagraph - }; + XElement[] content = { idx == 0 ? emptyParagraph : null, table, emptyParagraph }; return content; } @@ -791,11 +826,7 @@ private static XElement[] AssembledConjoinedRevisionContent( paraAfter = emptyParagraph; } - XElement[] revisionInTable = - { - ci.RevisionElement, - paraAfter - }; + XElement[] revisionInTable = { ci.RevisionElement, paraAfter }; // At this point, content might contain a footnote or endnote reference. // Need to add the footnote / endnote into the consolidated document (with the same @@ -818,15 +849,19 @@ private static XElement[] AssembledConjoinedRevisionContent( } } - private static void AddFootnotes(ConsolidationInfo ci, WordprocessingDocument wDocConsolidated, ref int maxFootnoteId) + private static void AddFootnotes( + ConsolidationInfo ci, + WordprocessingDocument wDocConsolidated, + ref int maxFootnoteId + ) { if (ci.RevisionElement.Descendants(W.footnoteReference).Any()) { var footnoteXDoc = wDocConsolidated.MainDocumentPart.FootnotesPart.GetXDocument(); foreach (var footnoteReference in ci.RevisionElement.Descendants(W.footnoteReference)) { - var id = (int) footnoteReference.Attribute(W.id); - var footnote = ci.Footnotes.FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var id = (int)footnoteReference.Attribute(W.id); + var footnote = ci.Footnotes.FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (footnote != null) { var newId = ++maxFootnoteId; @@ -842,15 +877,19 @@ private static void AddFootnotes(ConsolidationInfo ci, WordprocessingDocument wD } } - private static void AddEndnotes(ConsolidationInfo ci, WordprocessingDocument wDocConsolidated, ref int maxEndnoteId) + private static void AddEndnotes( + ConsolidationInfo ci, + WordprocessingDocument wDocConsolidated, + ref int maxEndnoteId + ) { if (ci.RevisionElement.Descendants(W.endnoteReference).Any()) { var endnoteXDoc = wDocConsolidated.MainDocumentPart.EndnotesPart.GetXDocument(); foreach (var endnoteReference in ci.RevisionElement.Descendants(W.endnoteReference)) { - var id = (int) endnoteReference.Attribute(W.id); - var endnote = ci.Endnotes.FirstOrDefault(fn => (int) fn.Attribute(W.id) == id); + var id = (int)endnoteReference.Attribute(W.id); + var endnote = ci.Endnotes.FirstOrDefault(fn => (int)fn.Attribute(W.id) == id); if (endnote != null) { var newId = ++maxEndnoteId; @@ -871,19 +910,28 @@ private static void AddToAnnotation( WordprocessingDocument consolidatedWDoc, XElement elementToInsertAfter, ConsolidationInfo consolidationInfo, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { var packageOfDeletedContent = wDocDelta.MainDocumentPart.OpenXmlPackage.GetPackage(); var packageOfNewContent = consolidatedWDoc.MainDocumentPart.OpenXmlPackage.GetPackage(); var partInDeletedDocument = packageOfDeletedContent.GetPart(wDocDelta.MainDocumentPart.Uri); var partInNewDocument = packageOfNewContent.GetPart(consolidatedWDoc.MainDocumentPart.Uri); - consolidationInfo.RevisionElement = - MoveRelatedPartsToDestination(partInDeletedDocument, partInNewDocument, consolidationInfo.RevisionElement); - - var clonedForHashing = (XElement) CloneBlockLevelContentForHashing(consolidatedWDoc.MainDocumentPart, - consolidationInfo.RevisionElement, false, settings); + consolidationInfo.RevisionElement = MoveRelatedPartsToDestination( + partInDeletedDocument, + partInNewDocument, + consolidationInfo.RevisionElement + ); + + var clonedForHashing = (XElement)CloneBlockLevelContentForHashing( + consolidatedWDoc.MainDocumentPart, + consolidationInfo.RevisionElement, + false, + settings + ); clonedForHashing.Descendants().Where(d => d.Name == W.ins || d.Name == W.del).Attributes(W.id).Remove(); - var shaString = clonedForHashing.ToString(SaveOptions.DisableFormatting) + var shaString = clonedForHashing + .ToString(SaveOptions.DisableFormatting) .Replace(" xmlns=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"", ""); var sha1Hash = WmlComparerUtil.SHA1HashStringForUTF8String(shaString); consolidationInfo.RevisionString = shaString; @@ -903,9 +951,8 @@ private static void AddTableGridStyleToStylesPart(StyleDefinitionsPart styleDefi { var sXDoc = styleDefinitionsPart.GetXDocument(); var tableGridStyle = sXDoc - .Root? - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "TableGridForRevisions"); + .Root?.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "TableGridForRevisions"); if (tableGridStyle == null) { @@ -958,9 +1005,8 @@ private static void AddTableGridStyleToStylesPart(StyleDefinitionsPart styleDefi } var tableNormalStyle = sXDoc - .Root - .Elements(W.style) - .FirstOrDefault(s => (string) s.Attribute(W.styleId) == "TableNormal"); + .Root.Elements(W.style) + .FirstOrDefault(s => (string)s.Attribute(W.styleId) == "TableNormal"); if (tableNormalStyle == null) { var tableNormalStyleMarkup = diff --git a/Clippit/Comparer/WmlComparer.Public.Methods.GetRevisions.cs b/Clippit/Comparer/WmlComparer.Public.Methods.GetRevisions.cs index 62a65cf0..3174ba72 100644 --- a/Clippit/Comparer/WmlComparer.Public.Methods.GetRevisions.cs +++ b/Clippit/Comparer/WmlComparer.Public.Methods.GetRevisions.cs @@ -28,8 +28,7 @@ public static List GetRevisions(WmlDocument source, WmlComp RemoveExistingPowerToolsMarkup(wDoc); var contentParent = wDoc.MainDocumentPart.GetXDocument().Root?.Element(W.body); - var atomList = - CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings).ToArray(); + var atomList = CreateComparisonUnitAtomList(wDoc.MainDocumentPart, contentParent, settings).ToArray(); if (False) { @@ -46,10 +45,14 @@ public static List GetRevisions(WmlDocument source, WmlComp var key = a.CorrelationStatus.ToString(); if (a.CorrelationStatus != CorrelationStatus.Equal) { - var rt = new XElement(a.RevTrackElement.Name, - new XAttribute(XNamespace.Xmlns + "w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"), - a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid)); + var rt = new XElement( + a.RevTrackElement.Name, + new XAttribute( + XNamespace.Xmlns + "w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + ), + a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid) + ); key += rt.ToString(SaveOptions.DisableFormatting); } @@ -57,9 +60,7 @@ public static List GetRevisions(WmlDocument source, WmlComp }) .ToList(); - var revisions = grouped - .Where(k => k.Key != "Equal") - .ToList(); + var revisions = grouped.Where(k => k.Key != "Equal").ToList(); if (False) { @@ -88,16 +89,17 @@ public static List GetRevisions(WmlDocument source, WmlComp var revTrackElement = rg.First().RevTrackElement; rev.RevisionXElement = revTrackElement; - rev.Author = (string) revTrackElement.Attribute(W.author); + rev.Author = (string)revTrackElement.Attribute(W.author); rev.ContentXElement = rg.First().ContentElement; - rev.Date = (string) revTrackElement.Attribute(W.date); + rev.Date = (string)revTrackElement.Attribute(W.date); rev.PartUri = wDoc.MainDocumentPart.Uri; rev.PartContentType = wDoc.MainDocumentPart.ContentType; if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name)) { - rev.Text = rg - .Select(rgc => rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value) + rev.Text = rg.Select(rgc => + rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value + ) .StringConcatenate(); } @@ -105,10 +107,16 @@ public static List GetRevisions(WmlDocument source, WmlComp }) .ToList(); - var footnotesRevisionList = - GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.FootnotesPart, W.footnote, settings); - var endnotesRevisionList = - GetFootnoteEndnoteRevisionList(wDoc.MainDocumentPart.EndnotesPart, W.endnote, settings); + var footnotesRevisionList = GetFootnoteEndnoteRevisionList( + wDoc.MainDocumentPart.FootnotesPart, + W.footnote, + settings + ); + var endnotesRevisionList = GetFootnoteEndnoteRevisionList( + wDoc.MainDocumentPart.EndnotesPart, + W.endnote, + settings + ); var finalRevisionList = mainDocPartRevisionList .Concat(footnotesRevisionList) @@ -121,7 +129,8 @@ public static List GetRevisions(WmlDocument source, WmlComp private static IEnumerable GetFootnoteEndnoteRevisionList( OpenXmlPart footnotesEndnotesPart, XName footnoteEndnoteElementName, - WmlComparerSettings settings) + WmlComparerSettings settings + ) { if (footnotesEndnotesPart == null) { @@ -130,7 +139,8 @@ private static IEnumerable GetFootnoteEndnoteRevisionList( var xDoc = footnotesEndnotesPart.GetXDocument(); var footnotesEndnotes = - xDoc.Root?.Elements(footnoteEndnoteElementName) ?? throw new OpenXmlPowerToolsException("Invalid document."); + xDoc.Root?.Elements(footnoteEndnoteElementName) + ?? throw new OpenXmlPowerToolsException("Invalid document."); var revisionsForPart = new List(); foreach (var fn in footnotesEndnotes) @@ -155,10 +165,14 @@ private static IEnumerable GetFootnoteEndnoteRevisionList( var key = a.CorrelationStatus.ToString(); if (a.CorrelationStatus != CorrelationStatus.Equal) { - var rt = new XElement(a.RevTrackElement.Name, - new XAttribute(XNamespace.Xmlns + "w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"), - a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid)); + var rt = new XElement( + a.RevTrackElement.Name, + new XAttribute( + XNamespace.Xmlns + "w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main" + ), + a.RevTrackElement.Attributes().Where(a2 => a2.Name != W.id && a2.Name != PtOpenXml.Unid) + ); key += rt.ToString(SaveOptions.DisableFormatting); } @@ -167,40 +181,38 @@ private static IEnumerable GetFootnoteEndnoteRevisionList( }) .ToList(); - var revisions = grouped - .Where(k => k.Key != "Equal") - .ToList(); + var revisions = grouped.Where(k => k.Key != "Equal").ToList(); - var thisNoteRevisionList = revisions - .Select(rg => + var thisNoteRevisionList = revisions.Select(rg => + { + var rev = new WmlComparerRevision(); + if (rg.Key.StartsWith("Inserted")) { - var rev = new WmlComparerRevision(); - if (rg.Key.StartsWith("Inserted")) - { - rev.RevisionType = WmlComparerRevisionType.Inserted; - } - else if (rg.Key.StartsWith("Deleted")) - { - rev.RevisionType = WmlComparerRevisionType.Deleted; - } + rev.RevisionType = WmlComparerRevisionType.Inserted; + } + else if (rg.Key.StartsWith("Deleted")) + { + rev.RevisionType = WmlComparerRevisionType.Deleted; + } - var revTrackElement = rg.First().RevTrackElement; - rev.RevisionXElement = revTrackElement; - rev.Author = (string) revTrackElement.Attribute(W.author); - rev.ContentXElement = rg.First().ContentElement; - rev.Date = (string) revTrackElement.Attribute(W.date); - rev.PartUri = footnotesEndnotesPart.Uri; - rev.PartContentType = footnotesEndnotesPart.ContentType; + var revTrackElement = rg.First().RevTrackElement; + rev.RevisionXElement = revTrackElement; + rev.Author = (string)revTrackElement.Attribute(W.author); + rev.ContentXElement = rg.First().ContentElement; + rev.Date = (string)revTrackElement.Attribute(W.date); + rev.PartUri = footnotesEndnotesPart.Uri; + rev.PartContentType = footnotesEndnotesPart.ContentType; - if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name)) - { - rev.Text = rg - .Select(rgc => rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value) - .StringConcatenate(); - } + if (!RevElementsWithNoText.Contains(rev.ContentXElement.Name)) + { + rev.Text = rg.Select(rgc => + rgc.ContentElement.Name == W.pPr ? NewLine : rgc.ContentElement.Value + ) + .StringConcatenate(); + } - return rev; - }); + return rev; + }); revisionsForPart.AddRange(thisNoteRevisionList); } diff --git a/Clippit/Comparer/WmlComparer.Public.NestedTypes.cs b/Clippit/Comparer/WmlComparer.Public.NestedTypes.cs index 603468dc..e3839346 100644 --- a/Clippit/Comparer/WmlComparer.Public.NestedTypes.cs +++ b/Clippit/Comparer/WmlComparer.Public.NestedTypes.cs @@ -23,7 +23,7 @@ public class WmlComparerRevision public enum WmlComparerRevisionType { Inserted, - Deleted + Deleted, } } } diff --git a/Clippit/Comparer/WmlComparerExtensions.cs b/Clippit/Comparer/WmlComparerExtensions.cs index ddd62a3b..1ce91a47 100644 --- a/Clippit/Comparer/WmlComparerExtensions.cs +++ b/Clippit/Comparer/WmlComparerExtensions.cs @@ -11,7 +11,8 @@ public static class WmlComparerExtensions { public static XElement GetMainDocumentBody(this WordprocessingDocument wordDocument) { - return wordDocument.GetMainDocumentRoot().Element(W.body) ?? throw new ArgumentException("Invalid document."); + return wordDocument.GetMainDocumentRoot().Element(W.body) + ?? throw new ArgumentException("Invalid document."); } public static XElement GetMainDocumentRoot(this WordprocessingDocument wordDocument) diff --git a/Clippit/Comparer/WmlComparerUtil.cs b/Clippit/Comparer/WmlComparerUtil.cs index 13a2d515..b32c64af 100644 --- a/Clippit/Comparer/WmlComparerUtil.cs +++ b/Clippit/Comparer/WmlComparerUtil.cs @@ -44,7 +44,10 @@ public static ComparisonUnitGroupType ComparisonUnitGroupTypeFromLocalName(strin "tr" => ComparisonUnitGroupType.Row, "tc" => ComparisonUnitGroupType.Cell, "txbxContent" => ComparisonUnitGroupType.Textbox, - _ => throw new ArgumentOutOfRangeException(nameof(localName), $@"Unsupported localName: '{localName}'.") + _ => throw new ArgumentOutOfRangeException( + nameof(localName), + $@"Unsupported localName: '{localName}'." + ), }; } } diff --git a/Clippit/Core/PowerToolsBlock.cs b/Clippit/Core/PowerToolsBlock.cs index 8c4f99b2..9a85ccd1 100644 --- a/Clippit/Core/PowerToolsBlock.cs +++ b/Clippit/Core/PowerToolsBlock.cs @@ -20,12 +20,12 @@ namespace Clippit.Core /// /// /// [Your code using the strongly typed classes] - /// + /// /// using (new PowerToolsBlock(wordprocessingDocument)) /// { /// [Your code using the PowerTools] /// } - /// + /// /// [Your code using the strongly typed classes] /// /// @@ -51,7 +51,8 @@ public PowerToolsBlock(OpenXmlPackage package) public void Dispose() { - if (_package is null) return; + if (_package is null) + return; _package.EndPowerToolsBlock(); _package = null; diff --git a/Clippit/Core/StronglyTypedBlock.cs b/Clippit/Core/StronglyTypedBlock.cs index 693bdd1f..413d3639 100644 --- a/Clippit/Core/StronglyTypedBlock.cs +++ b/Clippit/Core/StronglyTypedBlock.cs @@ -7,7 +7,7 @@ namespace Clippit.Core { /// - /// Provides an elegant way of wrapping a set of invocations of the strongly typed + /// Provides an elegant way of wrapping a set of invocations of the strongly typed /// classes provided by the Open XML SDK) in a using statement that demarcates those /// invokations as one "block" before and after which the PowerTools can be used safely. /// @@ -19,12 +19,12 @@ namespace Clippit.Core /// /// /// [Your code using the PowerTools] - /// + /// /// using (new NonPowerToolsBlock(wordprocessingDocument)) /// { /// [Your code using the strongly typed classes] /// } - /// + /// /// [Your code using the PowerTools] /// /// @@ -50,7 +50,8 @@ public StronglyTypedBlock(OpenXmlPackage package) public void Dispose() { - if (_package == null) return; + if (_package == null) + return; _package.BeginPowerToolsBlock(); _package = null; diff --git a/Clippit/Excel/Builder/Cell.cs b/Clippit/Excel/Builder/Cell.cs index 5fb56a6d..7cf03a86 100644 --- a/Clippit/Excel/Builder/Cell.cs +++ b/Clippit/Excel/Builder/Cell.cs @@ -10,23 +10,30 @@ public static CellDfn[] Headers(params string[] headers) => headers.Select(value => String(value, true)).ToArray(); public static CellDfn String(string value, bool bold = false) => - new() { CellDataType = CellDataType.String, Value = RemoveForbiddenChars(value), Bold = bold }; + new() + { + CellDataType = CellDataType.String, + Value = RemoveForbiddenChars(value), + Bold = bold, + }; - public static CellDfn Number(int value) => - new() { CellDataType = CellDataType.Number, Value = value }; + public static CellDfn Number(int value) => new() { CellDataType = CellDataType.Number, Value = value }; - public static CellDfn Number(long value) => - new() { CellDataType = CellDataType.Number, Value = value }; + public static CellDfn Number(long value) => new() { CellDataType = CellDataType.Number, Value = value }; - public static CellDfn Bool(bool? value) => - new() { CellDataType = CellDataType.Boolean, Value = value }; + public static CellDfn Bool(bool? value) => new() { CellDataType = CellDataType.Boolean, Value = value }; public static CellDfn Date(DateTime? value) { if (value is null || value.Value == DateTime.MinValue) return null; - return new CellDfn { CellDataType = CellDataType.Date, Value = value.Value, FormatCode = "mm-dd-yy" }; + return new CellDfn + { + CellDataType = CellDataType.Date, + Value = value.Value, + FormatCode = "mm-dd-yy", + }; } // From xml spec valid chars: @@ -34,7 +41,7 @@ public static CellDfn Date(DateTime? value) // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. private static readonly Regex s_xmlInvalidSymbolsRegex = new(@"[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF]", RegexOptions.Compiled); - + private static string RemoveForbiddenChars(string strInput) { if (string.IsNullOrWhiteSpace(strInput)) diff --git a/Clippit/Excel/ExcelFormula.cs b/Clippit/Excel/ExcelFormula.cs index 1d38c941..bd65eca9 100644 --- a/Clippit/Excel/ExcelFormula.cs +++ b/Clippit/Excel/ExcelFormula.cs @@ -10,32 +10,97 @@ namespace Clippit.Excel { internal enum EExcelFormula { - Formula = 1, Expression = 2, InfixTerms = 3, PreAndPostTerm = 4, - Term = 5, RefInfixTerms = 6, RefTerm = 7, Constant = 8, RefConstant = 9, - ErrorConstant = 10, LogicalConstant = 11, NumericalConstant = 12, - SignificandPart = 13, WholeNumberPart = 14, FractionalPart = 15, - ExponentPart = 16, StringConstant = 17, StringCharacter = 18, HighCharacter = 19, - ArrayConstant = 20, ConstantListRows = 21, ConstantListRow = 22, - InfixOperator = 23, ValueInfixOperator = 24, RefInfixOperator = 25, - UnionOperator = 26, IntersectionOperator = 27, RangeOperator = 28, - PostfixOperator = 29, PrefixOperator = 30, CellReference = 31, LocalCellReference = 32, - ExternalCellReference = 33, BookPrefix = 34, BangReference = 35, - SheetRangeReference = 36, SingleSheetPrefix = 37, SingleSheetReference = 38, - SingleSheetArea = 39, SingleSheet = 40, SheetRange = 41, WorkbookIndex = 42, - SheetName = 43, SheetNameCharacter = 44, SheetNameSpecial = 45, - SheetNameBaseCharacter = 46, A1Reference = 47, A1Cell = 48, A1Area = 49, - A1Column = 50, A1AbsoluteColumn = 51, A1RelativeColumn = 52, A1Row = 53, - A1AbsoluteRow = 54, A1RelativeRow = 55, CellFunctionCall = 56, UserDefinedFunctionCall = 57, - UserDefinedFunctionName = 58, ArgumentList = 59, Argument = 60, - ArgumentExpression = 61, ArgumentInfixTerms = 62, ArgumentPreAndPostTerm = 63, - ArgumentTerm = 64, ArgumentRefInfixTerms = 65, ArgumentRefTerm = 66, - ArgumentInfixOperator = 67, RefArgumentInfixOperator = 68, NameReference = 69, - ExternalName = 70, BangName = 71, Name = 72, NameStartCharacter = 73, - NameCharacter = 74, StructureReference = 75, TableIdentifier = 76, - TableName = 77, IntraTableReference = 78, InnerReference = 79, Keyword = 80, - KeywordList = 81, ColumnRange = 82, Column = 83, SimpleColumnName = 84, - EscapeColumnCharacter = 85, UnescapedColumnCharacter = 86, AnyNoSpaceColumnCharacter = 87, - SpacedComma = 88, SpacedLBracket = 89, SpacedRBracket = 90, ws = 91 + Formula = 1, + Expression = 2, + InfixTerms = 3, + PreAndPostTerm = 4, + Term = 5, + RefInfixTerms = 6, + RefTerm = 7, + Constant = 8, + RefConstant = 9, + ErrorConstant = 10, + LogicalConstant = 11, + NumericalConstant = 12, + SignificandPart = 13, + WholeNumberPart = 14, + FractionalPart = 15, + ExponentPart = 16, + StringConstant = 17, + StringCharacter = 18, + HighCharacter = 19, + ArrayConstant = 20, + ConstantListRows = 21, + ConstantListRow = 22, + InfixOperator = 23, + ValueInfixOperator = 24, + RefInfixOperator = 25, + UnionOperator = 26, + IntersectionOperator = 27, + RangeOperator = 28, + PostfixOperator = 29, + PrefixOperator = 30, + CellReference = 31, + LocalCellReference = 32, + ExternalCellReference = 33, + BookPrefix = 34, + BangReference = 35, + SheetRangeReference = 36, + SingleSheetPrefix = 37, + SingleSheetReference = 38, + SingleSheetArea = 39, + SingleSheet = 40, + SheetRange = 41, + WorkbookIndex = 42, + SheetName = 43, + SheetNameCharacter = 44, + SheetNameSpecial = 45, + SheetNameBaseCharacter = 46, + A1Reference = 47, + A1Cell = 48, + A1Area = 49, + A1Column = 50, + A1AbsoluteColumn = 51, + A1RelativeColumn = 52, + A1Row = 53, + A1AbsoluteRow = 54, + A1RelativeRow = 55, + CellFunctionCall = 56, + UserDefinedFunctionCall = 57, + UserDefinedFunctionName = 58, + ArgumentList = 59, + Argument = 60, + ArgumentExpression = 61, + ArgumentInfixTerms = 62, + ArgumentPreAndPostTerm = 63, + ArgumentTerm = 64, + ArgumentRefInfixTerms = 65, + ArgumentRefTerm = 66, + ArgumentInfixOperator = 67, + RefArgumentInfixOperator = 68, + NameReference = 69, + ExternalName = 70, + BangName = 71, + Name = 72, + NameStartCharacter = 73, + NameCharacter = 74, + StructureReference = 75, + TableIdentifier = 76, + TableName = 77, + IntraTableReference = 78, + InnerReference = 79, + Keyword = 80, + KeywordList = 81, + ColumnRange = 82, + Column = 83, + SimpleColumnName = 84, + EscapeColumnCharacter = 85, + UnescapedColumnCharacter = 86, + AnyNoSpaceColumnCharacter = 87, + SpacedComma = 88, + SpacedLBracket = 89, + SpacedRBracket = 90, + ws = 91, }; internal class ExcelFormula : PegCharParser @@ -43,14 +108,11 @@ internal class ExcelFormula : PegCharParser private static readonly EncodingClass EncodingClass = EncodingClass.ascii; private static readonly UnicodeDetection UnicodeDetection = UnicodeDetection.notApplicable; - public ExcelFormula() : base() - { - } + public ExcelFormula() + : base() { } public ExcelFormula(string src, TextWriter fErrOut) - : base(src, fErrOut) - { - } + : base(src, fErrOut) { } public override string GetRuleNameFromId(int id) { @@ -74,9 +136,7 @@ public override void GetProperties(out EncodingClass encoding, out UnicodeDetect public bool Formula() /*Formula: Expression (!./FATAL<"end of line expected">);*/ { - return And(() => - Expression() - && (Not(Any) || Fatal("end of line expected"))); + return And(() => Expression() && (Not(Any) || Fatal("end of line expected"))); } public bool Expression() /*Expression: ws InfixTerms;*/ @@ -86,50 +146,37 @@ public override void GetProperties(out EncodingClass encoding, out UnicodeDetect public bool InfixTerms() /*InfixTerms: PreAndPostTerm (InfixOperator ws PreAndPostTerm)*;*/ { - return And(() => - PreAndPostTerm() - && OptRepeat(() => - And(() => - InfixOperator() - && ws() - && PreAndPostTerm()))); + return And( + () => PreAndPostTerm() && OptRepeat(() => And(() => InfixOperator() && ws() && PreAndPostTerm())) + ); } public bool PreAndPostTerm() /*PreAndPostTerm: (PrefixOperator ws)* Term (PostfixOperator ws)*;*/ { - return And(() => - OptRepeat(() => And(() => PrefixOperator() && ws())) - && Term() - && OptRepeat(() => And(() => PostfixOperator() && ws()))); + return And( + () => + OptRepeat(() => And(() => PrefixOperator() && ws())) + && Term() + && OptRepeat(() => And(() => PostfixOperator() && ws())) + ); } public bool Term() /*Term: (RefInfixTerms / '(' Expression ')' / Constant) ws;*/ { - return And(() => - ( - RefInfixTerms() - || And(() => Char('(') && Expression() && Char(')')) - || Constant()) - && ws()); + return And( + () => (RefInfixTerms() || And(() => Char('(') && Expression() && Char(')')) || Constant()) && ws() + ); } public bool RefInfixTerms() /*RefInfixTerms: RefTerm (RefInfixOperator ws RefTerm)*;*/ { - return And(() => - RefTerm() - && OptRepeat(() => - And(() => RefInfixOperator() && ws() && RefTerm()))); + return And(() => RefTerm() && OptRepeat(() => And(() => RefInfixOperator() && ws() && RefTerm()))); } public bool RefTerm() /*RefTerm: '(' ws RefInfixTerms ')' / RefConstant / CellFunctionCall / CellReference / UserDefinedFunctionCall / NameReference / StructureReference;*/ { - return - And(() => - Char('(') - && ws() - && RefInfixTerms() - && Char(')')) + return And(() => Char('(') && ws() && RefInfixTerms() && Char(')')) || RefConstant() || CellFunctionCall() || CellReference() @@ -138,15 +185,12 @@ public bool RefTerm() /*RefTerm: '(' ws RefInfixTerms ')' / RefConstant / CellFu || StructureReference(); } - public bool - Constant() /*^^Constant: ErrorConstant / LogicalConstant / NumericalConstant / StringConstant / ArrayConstant;*/ + public bool Constant() /*^^Constant: ErrorConstant / LogicalConstant / NumericalConstant / StringConstant / ArrayConstant;*/ { - return TreeNT((int)EExcelFormula.Constant, () => - ErrorConstant() - || LogicalConstant() - || NumericalConstant() - || StringConstant() - || ArrayConstant()); + return TreeNT( + (int)EExcelFormula.Constant, + () => ErrorConstant() || LogicalConstant() || NumericalConstant() || StringConstant() || ArrayConstant() + ); } public bool RefConstant() /*RefConstant: '#REF!';*/ @@ -154,11 +198,9 @@ public bool return Char('#', 'R', 'E', 'F', '!'); } - public bool - ErrorConstant() /*ErrorConstant: RefConstant / '#DIV/0!' / '#N/A' / '#NAME?' / '#NULL!' / '#NUM!' / '#VALUE!' / '#GETTING_DATA';*/ + public bool ErrorConstant() /*ErrorConstant: RefConstant / '#DIV/0!' / '#N/A' / '#NAME?' / '#NULL!' / '#NUM!' / '#VALUE!' / '#GETTING_DATA';*/ { - return - RefConstant() + return RefConstant() || Char('#', 'D', 'I', 'V', '/', '0', '!') || Char('#', 'N', '/', 'A') || Char('#', 'N', 'A', 'M', 'E', '?') @@ -175,19 +217,12 @@ public bool public bool NumericalConstant() /*NumericalConstant: '-'? SignificandPart ExponentPart?;*/ { - return And(() => - Option(() => Char('-')) - && SignificandPart() - && Option(ExponentPart)); + return And(() => Option(() => Char('-')) && SignificandPart() && Option(ExponentPart)); } public bool SignificandPart() /*SignificandPart: WholeNumberPart FractionalPart? / FractionalPart;*/ { - return - And(() => - WholeNumberPart() - && Option(FractionalPart)) - || FractionalPart(); + return And(() => WholeNumberPart() && Option(FractionalPart)) || FractionalPart(); } public bool WholeNumberPart() /*WholeNumberPart: [0-9]+;*/ @@ -202,27 +237,17 @@ public bool public bool ExponentPart() /*ExponentPart: 'E' ('+' / '-')? [0-9]*;*/ { - return And(() => - Char('E') - && Option(() => Char('+') || Char('-')) - && OptRepeat(() => In('0', '9'))); + return And(() => Char('E') && Option(() => Char('+') || Char('-')) && OptRepeat(() => In('0', '9'))); } public bool StringConstant() /*StringConstant: '"' ('""'/StringCharacter)* '"';*/ { - return And(() => - Char('"') - && OptRepeat(() => Char('"', '"') || StringCharacter()) - && Char('"')); + return And(() => Char('"') && OptRepeat(() => Char('"', '"') || StringCharacter()) && Char('"')); } public bool StringCharacter() /*StringCharacter: [#-~] / '!' / ' ' / HighCharacter;*/ { - return - In('#', '~') - || Char('!') - || Char(' ') - || HighCharacter(); + return In('#', '~') || Char('!') || Char(' ') || HighCharacter(); } public bool HighCharacter() /*HighCharacter: [#x80-#xFFFF];*/ @@ -232,24 +257,23 @@ public bool public bool ArrayConstant() /*^^ArrayConstant: '{' ConstantListRows '}';*/ { - return TreeNT((int)EExcelFormula.ArrayConstant, () => - And(() => Char('{') && ConstantListRows() && Char('}'))); + return TreeNT( + (int)EExcelFormula.ArrayConstant, + () => And(() => Char('{') && ConstantListRows() && Char('}')) + ); } public bool ConstantListRows() /*ConstantListRows: ConstantListRow (';' ConstantListRow)*;*/ { - return And(() => - ConstantListRow() - && OptRepeat(() => - And(() => Char(';') && ConstantListRow()))); + return And(() => ConstantListRow() && OptRepeat(() => And(() => Char(';') && ConstantListRow()))); } public bool ConstantListRow() /*^^ConstantListRow: Constant (',' Constant)*;*/ { - return TreeNT((int)EExcelFormula.ConstantListRow, () => - And(() => - Constant() - && OptRepeat(() => And(() => Char(',') && Constant())))); + return TreeNT( + (int)EExcelFormula.ConstantListRow, + () => And(() => Constant() && OptRepeat(() => And(() => Char(',') && Constant()))) + ); } public bool InfixOperator() /*InfixOperator: RefInfixOperator / ValueInfixOperator;*/ @@ -257,49 +281,39 @@ public bool return RefInfixOperator() || ValueInfixOperator(); } - public bool - ValueInfixOperator() /*^^ValueInfixOperator: '<>' / '>=' / '<=' / '^' / '*' / '/' / '+' / '-' / '&' / '=' / '<' / '>';*/ + public bool ValueInfixOperator() /*^^ValueInfixOperator: '<>' / '>=' / '<=' / '^' / '*' / '/' / '+' / '-' / '&' / '=' / '<' / '>';*/ { - return TreeNT((int)EExcelFormula.ValueInfixOperator, () => - OneOfLiterals(s_optimizedLiterals0)); + return TreeNT((int)EExcelFormula.ValueInfixOperator, () => OneOfLiterals(s_optimizedLiterals0)); } public bool RefInfixOperator() /*RefInfixOperator: RangeOperator / UnionOperator / IntersectionOperator;*/ { - return - RangeOperator() - || UnionOperator() - || IntersectionOperator(); + return RangeOperator() || UnionOperator() || IntersectionOperator(); } public bool UnionOperator() /*^^UnionOperator: ',';*/ { - return TreeNT((int)EExcelFormula.UnionOperator, () => - Char(',')); + return TreeNT((int)EExcelFormula.UnionOperator, () => Char(',')); } public bool IntersectionOperator() /*^^IntersectionOperator: ' ';*/ { - return TreeNT((int)EExcelFormula.IntersectionOperator, () => - Char(' ')); + return TreeNT((int)EExcelFormula.IntersectionOperator, () => Char(' ')); } public bool RangeOperator() /*^^RangeOperator: ':';*/ { - return TreeNT((int)EExcelFormula.RangeOperator, () => - Char(':')); + return TreeNT((int)EExcelFormula.RangeOperator, () => Char(':')); } public bool PostfixOperator() /*^^PostfixOperator: '%';*/ { - return TreeNT((int)EExcelFormula.PostfixOperator, () => - Char('%')); + return TreeNT((int)EExcelFormula.PostfixOperator, () => Char('%')); } public bool PrefixOperator() /*^^PrefixOperator: '+' / '-';*/ { - return TreeNT((int)EExcelFormula.PrefixOperator, () => - Char('+') || Char('-')); + return TreeNT((int)EExcelFormula.PrefixOperator, () => Char('+') || Char('-')); } public bool CellReference() /*CellReference: ExternalCellReference / LocalCellReference;*/ @@ -312,13 +326,9 @@ public bool return A1Reference(); } - public bool - ExternalCellReference() /*ExternalCellReference: BangReference / SheetRangeReference / SingleSheetReference;*/ + public bool ExternalCellReference() /*ExternalCellReference: BangReference / SheetRangeReference / SingleSheetReference;*/ { - return - BangReference() - || SheetRangeReference() - || SingleSheetReference(); + return BangReference() || SheetRangeReference() || SingleSheetReference(); } public bool BookPrefix() /*BookPrefix: WorkbookIndex '!';*/ @@ -328,28 +338,22 @@ public bool public bool BangReference() /*BangReference: '!' (A1Reference / '#REF!');*/ { - return And(() => - Char('!') - && (A1Reference() || Char('#', 'R', 'E', 'F', '!'))); + return And(() => Char('!') && (A1Reference() || Char('#', 'R', 'E', 'F', '!'))); } public bool SheetRangeReference() /*SheetRangeReference: SheetRange '!' A1Reference;*/ { - return And(() => SheetRange() && Char('!') && A1Reference()); } public bool SingleSheetPrefix() /*SingleSheetPrefix: SingleSheet '!';*/ { - return And(() => SingleSheet() && Char('!')); } public bool SingleSheetReference() /*SingleSheetReference: SingleSheetPrefix (A1Reference / '#REF!');*/ { - return And(() => - SingleSheetPrefix() - && (A1Reference() || Char('#', 'R', 'E', 'F', '!'))); + return And(() => SingleSheetPrefix() && (A1Reference() || Char('#', 'R', 'E', 'F', '!'))); } public bool SingleSheetArea() /*SingleSheetArea: SingleSheetPrefix A1Area;*/ @@ -359,86 +363,75 @@ public bool public bool SingleSheet() /*SingleSheet: WorkbookIndex? SheetName / '\'' WorkbookIndex? SheetNameSpecial '\'';*/ { - return - And(() => - Option(WorkbookIndex) - && SheetName()) - || And(() => - Char('\'') - && Option(WorkbookIndex) - && SheetNameSpecial() - && Char('\'')); - } - - public bool - SheetRange() /*SheetRange: WorkbookIndex? SheetName ':' SheetName / '\'' WorkbookIndex? SheetNameSpecial ':' SheetNameSpecial '\'';*/ - { - return - And(() => - Option(WorkbookIndex) - && SheetName() - && Char(':') - && SheetName()) - || And(() => - Char('\'') - && Option(WorkbookIndex) - && SheetNameSpecial() - && Char(':') - && SheetNameSpecial() - && Char('\'')); + return And(() => Option(WorkbookIndex) && SheetName()) + || And(() => Char('\'') && Option(WorkbookIndex) && SheetNameSpecial() && Char('\'')); + } + + public bool SheetRange() /*SheetRange: WorkbookIndex? SheetName ':' SheetName / '\'' WorkbookIndex? SheetNameSpecial ':' SheetNameSpecial '\'';*/ + { + return And(() => Option(WorkbookIndex) && SheetName() && Char(':') && SheetName()) + || And( + () => + Char('\'') + && Option(WorkbookIndex) + && SheetNameSpecial() + && Char(':') + && SheetNameSpecial() + && Char('\'') + ); } public bool WorkbookIndex() /*^^WorkbookIndex: '[' WholeNumberPart ']';*/ { - return TreeNT((int)EExcelFormula.WorkbookIndex, () => - And(() => Char('[') && WholeNumberPart() && Char(']'))); + return TreeNT( + (int)EExcelFormula.WorkbookIndex, + () => And(() => Char('[') && WholeNumberPart() && Char(']')) + ); } public bool SheetName() /*^^SheetName: SheetNameCharacter+;*/ { - return TreeNT((int)EExcelFormula.SheetName, () => - PlusRepeat(SheetNameCharacter)); + return TreeNT((int)EExcelFormula.SheetName, () => PlusRepeat(SheetNameCharacter)); } public bool SheetNameCharacter() /*SheetNameCharacter: [A-Za-z0-9._] / HighCharacter;*/ { - return - (In('A', 'Z', 'a', 'z', '0', '9') || OneOf("._")) - || HighCharacter(); + return (In('A', 'Z', 'a', 'z', '0', '9') || OneOf("._")) || HighCharacter(); } public bool SheetNameSpecial() /*^^SheetNameSpecial: SheetNameBaseCharacter ('\'\''* SheetNameBaseCharacter)*;*/ { - return TreeNT((int)EExcelFormula.SheetNameSpecial, () => - And(() => - SheetNameBaseCharacter() - && OptRepeat(() => - And(() => - OptRepeat(() => Char('\'', '\'')) - && SheetNameBaseCharacter())))); + return TreeNT( + (int)EExcelFormula.SheetNameSpecial, + () => + And( + () => + SheetNameBaseCharacter() + && OptRepeat(() => And(() => OptRepeat(() => Char('\'', '\'')) && SheetNameBaseCharacter())) + ) + ); } - public bool - SheetNameBaseCharacter() /*SheetNameBaseCharacter: [A-Za-z0-9!"#$%&()+,-.;<=>@^_`{|}~ ] / HighCharacter;*/ + public bool SheetNameBaseCharacter() /*SheetNameBaseCharacter: [A-Za-z0-9!"#$%&()+,-.;<=>@^_`{|}~ ] / HighCharacter;*/ { return OneOf(s_optimizedCharset0) || HighCharacter(); } public bool A1Reference() /*^^A1Reference: (A1Column ':' A1Column) / (A1Row ':' A1Row) / A1Area / A1Cell;*/ { - return TreeNT((int)EExcelFormula.A1Reference, () => - And(() => A1Column() && Char(':') && A1Column()) - || And(() => A1Row() && Char(':') && A1Row()) - || A1Area() - || A1Cell()); + return TreeNT( + (int)EExcelFormula.A1Reference, + () => + And(() => A1Column() && Char(':') && A1Column()) + || And(() => A1Row() && Char(':') && A1Row()) + || A1Area() + || A1Cell() + ); } public bool A1Cell() /*A1Cell: A1Column A1Row !NameCharacter;*/ { - return And(() => - A1Column() - && A1Row() - && Not(NameCharacter)); + return And(() => A1Column() && A1Row() && Not(NameCharacter)); } public bool A1Area() /*A1Area: A1Cell ':' A1Cell;*/ @@ -448,8 +441,7 @@ public bool public bool A1Column() /*^^A1Column: A1AbsoluteColumn / A1RelativeColumn;*/ { - return TreeNT((int)EExcelFormula.A1Column, () => - A1AbsoluteColumn() || A1RelativeColumn()); + return TreeNT((int)EExcelFormula.A1Column, () => A1AbsoluteColumn() || A1RelativeColumn()); } public bool A1AbsoluteColumn() /*A1AbsoluteColumn: '$' A1RelativeColumn;*/ @@ -457,11 +449,9 @@ public bool return And(() => Char('$') && A1RelativeColumn()); } - public bool - A1RelativeColumn() /*A1RelativeColumn: 'XF' [A-D] / 'X' [A-E] [A-Z] / [A-W][A-Z][A-Z] / [A-Z][A-Z] / [A-Z];*/ + public bool A1RelativeColumn() /*A1RelativeColumn: 'XF' [A-D] / 'X' [A-E] [A-Z] / [A-W][A-Z][A-Z] / [A-Z][A-Z] / [A-Z];*/ { - return - And(() => Char('X', 'F') && In('A', 'D')) + return And(() => Char('X', 'F') && In('A', 'D')) || And(() => Char('X') && In('A', 'E') && In('A', 'Z')) || And(() => In('A', 'W') && In('A', 'Z') && In('A', 'Z')) || And(() => In('A', 'Z') && In('A', 'Z')) @@ -470,8 +460,7 @@ public bool public bool A1Row() /*^^A1Row: A1AbsoluteRow / A1RelativeRow;*/ { - return TreeNT((int)EExcelFormula.A1Row, () => - A1AbsoluteRow() || A1RelativeRow()); + return TreeNT((int)EExcelFormula.A1Row, () => A1AbsoluteRow() || A1RelativeRow()); } public bool A1AbsoluteRow() /*A1AbsoluteRow: '$' A1RelativeRow;*/ @@ -486,23 +475,18 @@ public bool public bool CellFunctionCall() /*^^CellFunctionCall: A1Cell '(' ArgumentList ')';*/ { - return TreeNT((int)EExcelFormula.CellFunctionCall, () => - And(() => - A1Cell() - && Char('(') - && ArgumentList() - && Char(')'))); + return TreeNT( + (int)EExcelFormula.CellFunctionCall, + () => And(() => A1Cell() && Char('(') && ArgumentList() && Char(')')) + ); } - public bool - UserDefinedFunctionCall() /*^^UserDefinedFunctionCall: UserDefinedFunctionName '(' ArgumentList ')';*/ + public bool UserDefinedFunctionCall() /*^^UserDefinedFunctionCall: UserDefinedFunctionName '(' ArgumentList ')';*/ { - return TreeNT((int)EExcelFormula.UserDefinedFunctionCall, () => - And(() => - UserDefinedFunctionName() - && Char('(') - && ArgumentList() - && Char(')'))); + return TreeNT( + (int)EExcelFormula.UserDefinedFunctionCall, + () => And(() => UserDefinedFunctionName() && Char('(') && ArgumentList() && Char(')')) + ); } public bool UserDefinedFunctionName() /*UserDefinedFunctionName: NameReference;*/ @@ -512,9 +496,7 @@ public bool public bool ArgumentList() /*ArgumentList: Argument (',' Argument)*;*/ { - return And(() => - Argument() - && OptRepeat(() => And(() => Char(',') && Argument()))); + return And(() => Argument() && OptRepeat(() => And(() => Char(',') && Argument()))); } public bool Argument() /*Argument: ArgumentExpression / ws;*/ @@ -524,63 +506,49 @@ public bool public bool ArgumentExpression() /*^^ArgumentExpression: ws ArgumentInfixTerms;*/ { - return TreeNT((int)EExcelFormula.ArgumentExpression, () => - And(() => ws() && ArgumentInfixTerms())); + return TreeNT((int)EExcelFormula.ArgumentExpression, () => And(() => ws() && ArgumentInfixTerms())); } - public bool - ArgumentInfixTerms() /*ArgumentInfixTerms: ArgumentPreAndPostTerm (ArgumentInfixOperator ws ArgumentPreAndPostTerm)*;*/ + public bool ArgumentInfixTerms() /*ArgumentInfixTerms: ArgumentPreAndPostTerm (ArgumentInfixOperator ws ArgumentPreAndPostTerm)*;*/ { - return And(() => - ArgumentPreAndPostTerm() - && OptRepeat(() => - And(() => - ArgumentInfixOperator() - && ws() - && ArgumentPreAndPostTerm()))); + return And( + () => + ArgumentPreAndPostTerm() + && OptRepeat(() => And(() => ArgumentInfixOperator() && ws() && ArgumentPreAndPostTerm())) + ); } - public bool - ArgumentPreAndPostTerm() /*ArgumentPreAndPostTerm: (PrefixOperator ws)* ArgumentTerm (PostfixOperator ws)*;*/ + public bool ArgumentPreAndPostTerm() /*ArgumentPreAndPostTerm: (PrefixOperator ws)* ArgumentTerm (PostfixOperator ws)*;*/ { - return And(() => - OptRepeat(() => And(() => PrefixOperator() && ws())) - && ArgumentTerm() - && OptRepeat(() => And(() => PostfixOperator() && ws()))); + return And( + () => + OptRepeat(() => And(() => PrefixOperator() && ws())) + && ArgumentTerm() + && OptRepeat(() => And(() => PostfixOperator() && ws())) + ); } public bool ArgumentTerm() /*ArgumentTerm: (ArgumentRefInfixTerms / '(' Expression ')' / Constant) ws;*/ { - return And(() => - ( - ArgumentRefInfixTerms() - || And(() => Char('(') && Expression() && Char(')')) - || Constant()) - && ws()); + return And( + () => + (ArgumentRefInfixTerms() || And(() => Char('(') && Expression() && Char(')')) || Constant()) && ws() + ); } - public bool - ArgumentRefInfixTerms() /*ArgumentRefInfixTerms: ArgumentRefTerm (RefArgumentInfixOperator ws ArgumentRefTerm)*;*/ + public bool ArgumentRefInfixTerms() /*ArgumentRefInfixTerms: ArgumentRefTerm (RefArgumentInfixOperator ws ArgumentRefTerm)*;*/ { - return And(() => - ArgumentRefTerm() - && OptRepeat(() => - And(() => - RefArgumentInfixOperator() - && ws() - && ArgumentRefTerm()))); + return And( + () => + ArgumentRefTerm() + && OptRepeat(() => And(() => RefArgumentInfixOperator() && ws() && ArgumentRefTerm())) + ); } - public bool - ArgumentRefTerm() /*ArgumentRefTerm: '(' ws RefInfixTerms ')' / RefConstant / CellFunctionCall / CellReference / UserDefinedFunctionCall + public bool ArgumentRefTerm() /*ArgumentRefTerm: '(' ws RefInfixTerms ')' / RefConstant / CellFunctionCall / CellReference / UserDefinedFunctionCall / NameReference / StructureReference;*/ { - return - And(() => - Char('(') - && ws() - && RefInfixTerms() - && Char(')')) + return And(() => Char('(') && ws() && RefInfixTerms() && Char(')')) || RefConstant() || CellFunctionCall() || CellReference() @@ -601,19 +569,15 @@ public bool public bool NameReference() /*^^NameReference: (ExternalName / Name) !'[';*/ { - return TreeNT((int)EExcelFormula.NameReference, () => - And(() => - (ExternalName() || Name()) - && Not(() => Char('[')))); + return TreeNT( + (int)EExcelFormula.NameReference, + () => And(() => (ExternalName() || Name()) && Not(() => Char('['))) + ); } public bool ExternalName() /*ExternalName: BangName / (SingleSheetPrefix / BookPrefix) Name;*/ { - return - BangName() - || And(() => - (SingleSheetPrefix() || BookPrefix()) - && Name()); + return BangName() || And(() => (SingleSheetPrefix() || BookPrefix()) && Name()); } public bool BangName() /*BangName: '!' Name;*/ @@ -623,34 +587,25 @@ public bool public bool Name() /*Name: NameStartCharacter NameCharacter*;*/ { - return And(() => - NameStartCharacter() - && OptRepeat(NameCharacter)); + return And(() => NameStartCharacter() && OptRepeat(NameCharacter)); } public bool NameStartCharacter() /*NameStartCharacter: [_\\A-Za-z] / HighCharacter;*/ { - return - (In('A', 'Z', 'a', 'z') || OneOf("_\\")) - || HighCharacter(); + return (In('A', 'Z', 'a', 'z') || OneOf("_\\")) || HighCharacter(); } public bool NameCharacter() /*NameCharacter: NameStartCharacter / [0-9] / '.' / '?' / HighCharacter;*/ { - return - NameStartCharacter() - || In('0', '9') - || Char('.') - || Char('?') - || HighCharacter(); + return NameStartCharacter() || In('0', '9') || Char('.') || Char('?') || HighCharacter(); } public bool StructureReference() /*^^StructureReference: TableIdentifier? IntraTableReference;*/ { - return TreeNT((int)EExcelFormula.StructureReference, () => - And(() => - Option(TableIdentifier) - && IntraTableReference())); + return TreeNT( + (int)EExcelFormula.StructureReference, + () => And(() => Option(TableIdentifier) && IntraTableReference()) + ); } public bool TableIdentifier() /*TableIdentifier: BookPrefix? TableName;*/ @@ -663,84 +618,51 @@ public bool return Name(); } - public bool - IntraTableReference() /*IntraTableReference: SpacedLBracket InnerReference SpacedRBracket / Keyword / '[' SimpleColumnName ']';*/ + public bool IntraTableReference() /*IntraTableReference: SpacedLBracket InnerReference SpacedRBracket / Keyword / '[' SimpleColumnName ']';*/ { - return - And(() => - SpacedLBracket() - && InnerReference() - && SpacedRBracket()) + return And(() => SpacedLBracket() && InnerReference() && SpacedRBracket()) || Keyword() - || And(() => - Char('[') - && SimpleColumnName() - && Char(']')); + || And(() => Char('[') && SimpleColumnName() && Char(']')); } public bool InnerReference() /*InnerReference: (KeywordList SpacedComma)? ColumnRange / KeywordList;*/ { - return - And(() => - Option(() => - And(() => KeywordList() && SpacedComma())) - && ColumnRange()) - || KeywordList(); + return And(() => Option(() => And(() => KeywordList() && SpacedComma())) && ColumnRange()) || KeywordList(); } public bool Keyword() /*Keyword: '[#All]' / '[#Data]' / '[#Headers]' / '[#Totals]' / '[#This Row]';*/ { - return - Char('[', '#', 'A', 'l', 'l', ']') + return Char('[', '#', 'A', 'l', 'l', ']') || Char('[', '#', 'D', 'a', 't', 'a', ']') || Char("[#Headers]") || Char("[#Totals]") || Char("[#This Row]"); } - public bool - KeywordList() /*KeywordList: '[#Headers]' SpacedComma '[#Data]' / '[#Data]' SpacedComma '[#Totals]' / Keyword;*/ + public bool KeywordList() /*KeywordList: '[#Headers]' SpacedComma '[#Data]' / '[#Data]' SpacedComma '[#Totals]' / Keyword;*/ { - return - And(() => - Char("[#Headers]") - && SpacedComma() - && Char('[', '#', 'D', 'a', 't', 'a', ']')) - || And(() => - Char('[', '#', 'D', 'a', 't', 'a', ']') - && SpacedComma() - && Char("[#Totals]")) + return And(() => Char("[#Headers]") && SpacedComma() && Char('[', '#', 'D', 'a', 't', 'a', ']')) + || And(() => Char('[', '#', 'D', 'a', 't', 'a', ']') && SpacedComma() && Char("[#Totals]")) || Keyword(); } public bool ColumnRange() /*ColumnRange: Column (':' Column)?;*/ { - return And(() => - Column() - && Option(() => And(() => Char(':') && Column()))); + return And(() => Column() && Option(() => And(() => Char(':') && Column()))); } public bool Column() /*Column: '[' ws SimpleColumnName ws ']' / SimpleColumnName;*/ { - return - And(() => - Char('[') - && ws() - && SimpleColumnName() - && ws() - && Char(']')) - || SimpleColumnName(); + return And(() => Char('[') && ws() && SimpleColumnName() && ws() && Char(']')) || SimpleColumnName(); } - public bool - SimpleColumnName() /*SimpleColumnName: AnyNoSpaceColumnCharacter+ (ws AnyNoSpaceColumnCharacter+)*;*/ + public bool SimpleColumnName() /*SimpleColumnName: AnyNoSpaceColumnCharacter+ (ws AnyNoSpaceColumnCharacter+)*;*/ { - return And(() => - PlusRepeat(AnyNoSpaceColumnCharacter) - && OptRepeat(() => - And(() => - ws() - && PlusRepeat(AnyNoSpaceColumnCharacter)))); + return And( + () => + PlusRepeat(AnyNoSpaceColumnCharacter) + && OptRepeat(() => And(() => ws() && PlusRepeat(AnyNoSpaceColumnCharacter))) + ); } public bool EscapeColumnCharacter() /*EscapeColumnCharacter: '\'' / '#' / '[' / ']';*/ @@ -748,26 +670,19 @@ public bool return Char('\'') || Char('#') || Char('[') || Char(']'); } - public bool - UnescapedColumnCharacter() /*UnescapedColumnCharacter: [A-Za-z0-9!"#$%&()*+,-./:;<=>?@\\^_`{|}~] / HighCharacter;*/ + public bool UnescapedColumnCharacter() /*UnescapedColumnCharacter: [A-Za-z0-9!"#$%&()*+,-./:;<=>?@\\^_`{|}~] / HighCharacter;*/ { return OneOf(s_optimizedCharset1) || HighCharacter(); } - public bool - AnyNoSpaceColumnCharacter() /*AnyNoSpaceColumnCharacter: ('\'' EscapeColumnCharacter) / UnescapedColumnCharacter;*/ + public bool AnyNoSpaceColumnCharacter() /*AnyNoSpaceColumnCharacter: ('\'' EscapeColumnCharacter) / UnescapedColumnCharacter;*/ { - return - And(() => Char('\'') && EscapeColumnCharacter()) - || UnescapedColumnCharacter(); + return And(() => Char('\'') && EscapeColumnCharacter()) || UnescapedColumnCharacter(); } public bool SpacedComma() /*SpacedComma: ' '? ',' ' '?;*/ { - return And(() => - Option(() => Char(' ')) - && Char(',') - && Option(() => Char(' '))); + return And(() => Option(() => Char(' ')) && Char(',') && Option(() => Char(' '))); } public bool SpacedLBracket() /*SpacedLBracket: '[' ' '?;*/ @@ -785,7 +700,6 @@ public bool return OptRepeat(() => Char(' ')); } - private static readonly OptimizedCharset s_optimizedCharset0; private static readonly OptimizedCharset s_optimizedCharset1; private static readonly OptimizedLiterals s_optimizedLiterals0; @@ -795,12 +709,35 @@ static ExcelFormula() { var ranges = new OptimizedCharset.Range[] { - new('A', 'Z'), new('a', 'z'), new('0', '9'), new(',', '.'), + new('A', 'Z'), + new('a', 'z'), + new('0', '9'), + new(',', '.'), }; var oneOfChars = new char[] { - '!', '"', '#', '$', '%', '&', '(', ')', '+', ';', '<', '=', '>', '@', '^', '_', '`', '{', '|', - '}', '~', ' ' + '!', + '"', + '#', + '$', + '%', + '&', + '(', + ')', + '+', + ';', + '<', + '=', + '>', + '@', + '^', + '_', + '`', + '{', + '|', + '}', + '~', + ' ', }; s_optimizedCharset0 = new OptimizedCharset(ranges, oneOfChars); } @@ -808,12 +745,39 @@ static ExcelFormula() { var ranges = new OptimizedCharset.Range[] { - new('A', 'Z'), new('a', 'z'), new('0', '9'), new(',', '.'), + new('A', 'Z'), + new('a', 'z'), + new('0', '9'), + new(',', '.'), }; var oneOfChars = new char[] { - '!', '"', '#', '$', '%', '&', '(', ')', '*', '+', '/', ':', ';', '<', '=', '>', '?', '@', '\\', - '^', '_', '`', '{', '|', '}', '~' + '!', + '"', + '#', + '$', + '%', + '&', + '(', + ')', + '*', + '+', + '/', + ':', + ';', + '<', + '=', + '>', + '?', + '@', + '\\', + '^', + '_', + '`', + '{', + '|', + '}', + '~', }; s_optimizedCharset1 = new OptimizedCharset(ranges, oneOfChars); } diff --git a/Clippit/Excel/PegBase.cs b/Clippit/Excel/PegBase.cs index b7b2a684..8d80e372 100644 --- a/Clippit/Excel/PegBase.cs +++ b/Clippit/Excel/PegBase.cs @@ -18,42 +18,73 @@ namespace Clippit.Excel { #region Input File Support - public enum EncodingClass { unicode, utf8, binary, ascii }; - public enum UnicodeDetection { notApplicable, BOM, FirstCharIsAscii }; + public enum EncodingClass + { + unicode, + utf8, + binary, + ascii, + }; + + public enum UnicodeDetection + { + notApplicable, + BOM, + FirstCharIsAscii, + }; + public class FileLoader { - public enum FileEncoding { none, ascii, binary, utf8, unicode, utf16be, utf16le, utf32le, utf32be, uniCodeBOM }; + public enum FileEncoding + { + none, + ascii, + binary, + utf8, + unicode, + utf16be, + utf16le, + utf32le, + utf32be, + uniCodeBOM, + }; + public FileLoader(EncodingClass encodingClass, UnicodeDetection detection, string path) { Encoding = GetEncoding(encodingClass, detection, path); _path = path; } + public bool IsBinaryFile() { return Encoding == FileEncoding.binary; } + public bool LoadFile(out byte[] src) { src = null; - if (!IsBinaryFile()) return false; - using var brdr = new BinaryReader(File.Open(_path, FileMode.Open,FileAccess.Read)); + if (!IsBinaryFile()) + return false; + using var brdr = new BinaryReader(File.Open(_path, FileMode.Open, FileAccess.Read)); src = brdr.ReadBytes((int)brdr.BaseStream.Length); return true; } + public bool LoadFile(out string src) { src = null; var textEncoding = FileEncodingToTextEncoding(); if (textEncoding == null) { - if (Encoding == FileEncoding.binary) return false; + if (Encoding == FileEncoding.binary) + return false; using var rd = new StreamReader(_path, true); src = rd.ReadToEnd(); return true; } else { - if (Encoding == FileEncoding.utf16be)//UTF16BE + if (Encoding == FileEncoding.utf16be) //UTF16BE { using var brdr = new BinaryReader(File.Open(_path, FileMode.Open, FileAccess.Read)); var bytes = brdr.ReadBytes((int)brdr.BaseStream.Length); @@ -73,25 +104,29 @@ public bool LoadFile(out string src) return true; } } - } private Encoding FileEncodingToTextEncoding() { switch (Encoding) { - case FileEncoding.utf8: return new UTF8Encoding(); + case FileEncoding.utf8: + return new UTF8Encoding(); case FileEncoding.utf32be: - case FileEncoding.utf32le: return new UTF32Encoding(); + case FileEncoding.utf32le: + return new UTF32Encoding(); case FileEncoding.unicode: case FileEncoding.utf16be: - case FileEncoding.utf16le: return new UnicodeEncoding(); - case FileEncoding.ascii: return new ASCIIEncoding(); + case FileEncoding.utf16le: + return new UnicodeEncoding(); + case FileEncoding.ascii: + return new ASCIIEncoding(); case FileEncoding.binary: - case FileEncoding.uniCodeBOM: return null; - default: Debug.Assert(false); + case FileEncoding.uniCodeBOM: + return null; + default: + Debug.Assert(false); return null; - } } @@ -99,13 +134,20 @@ private static FileEncoding DetermineUnicodeWhenFirstCharIsAscii(string path) { using var br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read)); var startBytes = br.ReadBytes(4); - if (startBytes.Length == 0) return FileEncoding.none; - if (startBytes.Length is 1 or 3) return FileEncoding.utf8; - if (startBytes.Length == 2 && startBytes[0] != 0) return FileEncoding.utf16le; - if (startBytes.Length == 2 && startBytes[0] == 0) return FileEncoding.utf16be; - if (startBytes[0] == 0 && startBytes[1] == 0) return FileEncoding.utf32be; - if (startBytes[0] == 0 && startBytes[1] != 0) return FileEncoding.utf16be; - if (startBytes[0] != 0 && startBytes[1] == 0) return FileEncoding.utf16le; + if (startBytes.Length == 0) + return FileEncoding.none; + if (startBytes.Length is 1 or 3) + return FileEncoding.utf8; + if (startBytes.Length == 2 && startBytes[0] != 0) + return FileEncoding.utf16le; + if (startBytes.Length == 2 && startBytes[0] == 0) + return FileEncoding.utf16be; + if (startBytes[0] == 0 && startBytes[1] == 0) + return FileEncoding.utf32be; + if (startBytes[0] == 0 && startBytes[1] != 0) + return FileEncoding.utf16be; + if (startBytes[0] != 0 && startBytes[1] == 0) + return FileEncoding.utf16le; return FileEncoding.utf8; } @@ -118,11 +160,11 @@ private FileEncoding GetEncoding(EncodingClass encodingClass, UnicodeDetection d { UnicodeDetection.FirstCharIsAscii => DetermineUnicodeWhenFirstCharIsAscii(path), UnicodeDetection.BOM => FileEncoding.uniCodeBOM, - _ => FileEncoding.unicode + _ => FileEncoding.unicode, }, EncodingClass.utf8 => FileEncoding.utf8, EncodingClass.binary => FileEncoding.binary, - _ => FileEncoding.none + _ => FileEncoding.none, }; } @@ -134,10 +176,9 @@ private FileEncoding GetEncoding(EncodingClass encodingClass, UnicodeDetection d public class PegException : Exception { public PegException() - : base("Fatal parsing error ocurred") - { - } + : base("Fatal parsing error ocurred") { } } + public struct PegError { internal SortedList _lineStarts; @@ -155,6 +196,7 @@ private void AddLineStarts(string s, int first, int last, ref int lineNo, out in } --colNo; } + public void GetLineAndCol(string s, int pos, out int lineNo, out int colNo) { for (var i = _lineStarts.Count; i > 0; --i) @@ -179,50 +221,68 @@ public void GetLineAndCol(string s, int pos, out int lineNo, out int colNo) } #endregion Error handling #region Syntax/Parse-Tree related classes - public enum ESpecialNodes { eFatal = -10001, eAnonymNTNode = -1000, eAnonymASTNode = -1001, eAnonymousNode = -100 } - public enum ECreatorPhase { eCreate, eCreationComplete, eCreateAndComplete } - public struct PegBegEnd//indices into the source string + public enum ESpecialNodes + { + eFatal = -10001, + eAnonymNTNode = -1000, + eAnonymASTNode = -1001, + eAnonymousNode = -100, + } + + public enum ECreatorPhase + { + eCreate, + eCreationComplete, + eCreateAndComplete, + } + + public struct PegBegEnd //indices into the source string { public int Length { get { return _posEnd - _posBeg; } } + public string GetAsString(string src) { Debug.Assert(src.Length >= _posEnd); return src.Substring(_posBeg, Length); } + public int _posBeg; public int _posEnd; } + public class PegNode : ICloneable { #region Constructors public PegNode(PegNode parent, int id, PegBegEnd match, PegNode child, PegNode next) { - parent_ = parent; id_ = id; child_ = child; next_ = next; + parent_ = parent; + id_ = id; + child_ = child; + next_ = next; match_ = match; } + public PegNode(PegNode parent, int id, PegBegEnd match, PegNode child) - : this(parent, id, match, child, null) - { - } + : this(parent, id, match, child, null) { } + public PegNode(PegNode parent, int id, PegBegEnd match) - : this(parent, id, match, null, null) - { } + : this(parent, id, match, null, null) { } + public PegNode(PegNode parent, int id) - : this(parent, id, new PegBegEnd(), null, null) - { - } + : this(parent, id, new PegBegEnd(), null, null) { } #endregion Constructors #region Public Members public virtual string GetAsString(string s) { return match_.GetAsString(s); } + public virtual PegNode Clone() { - var clone= new PegNode(parent_, id_, match_); + var clone = new PegNode(parent_, id_, match_); CloneSubTrees(clone); return clone; } @@ -230,7 +290,8 @@ public virtual PegNode Clone() #region Protected Members protected void CloneSubTrees(PegNode clone) { - PegNode child = null, next = null; + PegNode child = null, + next = null; if (child_ != null) { child = child_.Clone(); @@ -247,7 +308,9 @@ protected void CloneSubTrees(PegNode clone) #endregion Protected Members #region Data Members public int id_; - public PegNode parent_, child_, next_; + public PegNode parent_, + child_, + next_; public PegBegEnd match_; #endregion Data Members @@ -260,18 +323,30 @@ object ICloneable.Clone() #endregion } + internal struct PegTree { - internal enum AddPolicy { eAddAsChild, eAddAsSibling }; + internal enum AddPolicy + { + eAddAsChild, + eAddAsSibling, + }; + internal PegNode _root; internal PegNode _cur; internal AddPolicy _addPolicy; } + public abstract class PrintNode { public abstract int LenMaxLine(); public abstract bool IsLeaf(PegNode p); - public virtual bool IsSkip(PegNode p) { return false; } + + public virtual bool IsSkip(PegNode p) + { + return false; + } + public abstract void PrintNodeBeg(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel); public abstract void PrintNodeEnd(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel); public abstract int LenNodeBeg(PegNode p); @@ -281,6 +356,7 @@ public abstract class PrintNode public abstract int LenDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel); public abstract void PrintDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel); } + public class TreePrint : PrintNode { #region Data Members @@ -310,13 +386,13 @@ public void PrintTree(PegNode parent, int nOffsetLineBeg, int nLevel) _treeOut.Flush(); return; } - var bAlignVertical = - DetermineLineLength(parent, nOffsetLineBeg) > LenMaxLine(); + var bAlignVertical = DetermineLineLength(parent, nOffsetLineBeg) > LenMaxLine(); PrintNodeBeg(parent, bAlignVertical, ref nOffsetLineBeg, nLevel); var nOffset = nOffsetLineBeg; for (var p = parent.child_; p != null; p = p.next_) { - if (IsSkip(p)) continue; + if (IsSkip(p)) + continue; if (IsLeaf(p)) { @@ -330,14 +406,15 @@ public void PrintTree(PegNode parent, int nOffsetLineBeg, int nLevel) { nOffsetLineBeg = nOffset; } - while (p.next_ != null && IsSkip(p.next_)) p = p.next_; + while (p.next_ != null && IsSkip(p.next_)) + p = p.next_; if (p.next_ != null) { PrintDistNext(p, bAlignVertical, ref nOffsetLineBeg, nLevel); } } - PrintNodeEnd(parent, bAlignVertical, ref nOffsetLineBeg, nLevel); + PrintNodeEnd(parent, bAlignVertical, ref nOffsetLineBeg, nLevel); _treeOut.Flush(); } @@ -347,7 +424,8 @@ private int DetermineLineLength(PegNode parent, int nOffsetLineBeg) PegNode p; for (p = parent.child_; p != null; p = p.next_) { - if (IsSkip(p)) continue; + if (IsSkip(p)) + continue; if (IsLeaf(p)) { nLen += LenLeaf(p); @@ -364,9 +442,13 @@ private int DetermineLineLength(PegNode parent, int nOffsetLineBeg) nLen += LenNodeEnd(p); return nLen; } - public override int LenMaxLine() { return _nMaxLineLen; } - public override void - PrintNodeBeg(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) + + public override int LenMaxLine() + { + return _nMaxLineLen; + } + + public override void PrintNodeBeg(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) { PrintIdAsName(p); _treeOut.Write("<"); @@ -380,8 +462,8 @@ public override void ++nOffsetLineBeg; } } - public override void - PrintNodeEnd(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) + + public override void PrintNodeEnd(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) { if (bAlignVertical) { @@ -394,8 +476,17 @@ public override void ++nOffsetLineBeg; } } - public override int LenNodeBeg(PegNode p) { return LenIdAsName(p) + 1; } - public override int LenNodeEnd(PegNode p) { return 1; } + + public override int LenNodeBeg(PegNode p) + { + return LenIdAsName(p) + 1; + } + + public override int LenNodeEnd(PegNode p) + { + return 1; + } + public override void PrintLeaf(PegNode p, ref int nOffsetLineBeg, bool bAlignVertical) { if (_bVerbose) @@ -410,21 +501,24 @@ public override void PrintLeaf(PegNode p, ref int nOffsetLineBeg, bool bAlignVer _treeOut.Write(_src.Substring(p.match_._posBeg, p.match_._posEnd - p.match_._posBeg)); } _treeOut.Write("'"); - if (_bVerbose) _treeOut.Write('>'); + if (_bVerbose) + _treeOut.Write('>'); } + public override int LenLeaf(PegNode p) { var nLen = p.match_._posEnd - p.match_._posBeg + 2; - if (_bVerbose) nLen += LenIdAsName(p) + 2; + if (_bVerbose) + nLen += LenIdAsName(p) + 2; return nLen; } + public override bool IsLeaf(PegNode p) { return p.child_ == null; } - public override void - PrintDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) + public override void PrintDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) { if (bAlignVertical) { @@ -438,8 +532,7 @@ public override void } } - public override int - LenDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) + public override int LenDistNext(PegNode p, bool bAlignVertical, ref int nOffsetLineBeg, int nLevel) { return 1; } @@ -478,18 +571,21 @@ public virtual string GetRuleNameFromId(int id) (int)ESpecialNodes.eAnonymNTNode => "Nonterminal", (int)ESpecialNodes.eAnonymASTNode => "ASTNode", (int)ESpecialNodes.eAnonymousNode => "Node", - _ => id.ToString() + _ => id.ToString(), }; } + public virtual void GetProperties(out EncodingClass encoding, out UnicodeDetection detection) { encoding = EncodingClass.ascii; detection = UnicodeDetection.notApplicable; } + public int GetMaximumPosition() { return _maxPos; } + protected PegNode DefaultNodeCreator(ECreatorPhase phase, PegNode parentOrCreated, int id) { if (phase is ECreatorPhase.eCreate or ECreatorPhase.eCreateAndComplete) @@ -499,6 +595,7 @@ protected PegNode DefaultNodeCreator(ECreatorPhase phase, PegNode parentOrCreate _maxPos = parentOrCreated.match_._posEnd; return null; } + #region Constructors public PegBaseParser(TextWriter errOut) { @@ -517,7 +614,10 @@ public void Construct(TextWriter fOut) ResetTree(); } - public void Rewind() { _pos = 0; } + public void Rewind() + { + _pos = 0; + } public void SetErrorDestination(TextWriter errOut) { @@ -525,275 +625,311 @@ public void SetErrorDestination(TextWriter errOut) } #endregion Reinitialization, TextWriter access,Tree Access - #region Tree root access, Tree Node generation/display - public PegNode GetRoot() { return _tree._root; } - public void ResetTree() - { - _tree._root = null; - _tree._cur = null; - _tree._addPolicy = PegTree.AddPolicy.eAddAsChild; - } - - private void AddTreeNode(int nId, PegTree.AddPolicy newAddPolicy, Creator createNode, ECreatorPhase ePhase) - { - if (_bMute) return; - if (_tree._root == null) - { - _tree._root = _tree._cur = createNode(ePhase, _tree._cur, nId); - } - else if (_tree._addPolicy == PegTree.AddPolicy.eAddAsChild) - { - _tree._cur = _tree._cur.child_ = createNode(ePhase, _tree._cur, nId); - } - else - { - _tree._cur = _tree._cur.next_ = createNode(ePhase, _tree._cur.parent_, nId); - } - _tree._addPolicy = newAddPolicy; - } - - private void RestoreTree(PegNode prevCur, PegTree.AddPolicy prevPolicy) - { - if (_bMute) return; - if (prevCur == null) - { - _tree._root = null; - } - else if (prevPolicy == PegTree.AddPolicy.eAddAsChild) - { - prevCur.child_ = null; - } - else - { - prevCur.next_ = null; - } - _tree._cur = prevCur; - _tree._addPolicy = prevPolicy; - } - public bool TreeChars(Matcher toMatch) - { - return TreeCharsWithId((int)ESpecialNodes.eAnonymousNode, toMatch); - } - public bool TreeChars(Creator nodeCreator, Matcher toMatch) - { - return TreeCharsWithId(nodeCreator, (int)ESpecialNodes.eAnonymousNode, toMatch); - } - public bool TreeCharsWithId(int nId, Matcher toMatch) - { - return TreeCharsWithId(_nodeCreator, nId, toMatch); - } - public bool TreeCharsWithId(Creator nodeCreator, int nId, Matcher toMatch) - { - var pos = _pos; - if (toMatch()) - { - if (!_bMute) - { - AddTreeNode(nId, PegTree.AddPolicy.eAddAsSibling, nodeCreator, ECreatorPhase.eCreateAndComplete); - _tree._cur.match_._posBeg = pos; - _tree._cur.match_._posEnd = _pos; - } - return true; - } - return false; - } - public bool TreeNT(int nRuleId, Matcher toMatch) - { - return TreeNT(_nodeCreator, nRuleId, toMatch); - } - public bool TreeNT(Creator nodeCreator, int nRuleId, Matcher toMatch) - { - if (_bMute) return toMatch(); - var prevCur = _tree._cur; - var prevPolicy = _tree._addPolicy; - var posBeg = _pos; - AddTreeNode(nRuleId, PegTree.AddPolicy.eAddAsChild, nodeCreator, ECreatorPhase.eCreate); - var ruleNode = _tree._cur; - var bMatches = toMatch(); - if (!bMatches) RestoreTree(prevCur, prevPolicy); - else - { - ruleNode.match_._posBeg = posBeg; - ruleNode.match_._posEnd = _pos; - _tree._cur = ruleNode; - _tree._addPolicy = PegTree.AddPolicy.eAddAsSibling; - nodeCreator(ECreatorPhase.eCreationComplete, ruleNode, nRuleId); - } - return bMatches; - } - public bool TreeAST(int nRuleId, Matcher toMatch) - { - return TreeAST(_nodeCreator, nRuleId, toMatch); - } - public bool TreeAST(Creator nodeCreator, int nRuleId, Matcher toMatch) - { - if (_bMute) return toMatch(); - var bMatches = TreeNT(nodeCreator, nRuleId, toMatch); - if (bMatches) - { - if (_tree._cur.child_ != null && _tree._cur.child_.next_ == null && _tree._cur.parent_ != null) - { - if (_tree._cur.parent_.child_ == _tree._cur) - { - _tree._cur.parent_.child_ = _tree._cur.child_; - _tree._cur.child_.parent_ = _tree._cur.parent_; - _tree._cur = _tree._cur.child_; - } - else - { - PegNode prev; - for (prev = _tree._cur.parent_.child_; prev != null && prev.next_ != _tree._cur; prev = prev.next_) - { - } - if (prev != null) - { - prev.next_ = _tree._cur.child_; - _tree._cur.child_.parent_ = _tree._cur.parent_; - _tree._cur = _tree._cur.child_; - } - } - } - } - return bMatches; - } - public bool TreeNT(Matcher toMatch) - { - return TreeNT((int)ESpecialNodes.eAnonymNTNode, toMatch); - } - public bool TreeNT(Creator nodeCreator, Matcher toMatch) - { - return TreeNT(nodeCreator, (int)ESpecialNodes.eAnonymNTNode, toMatch); - } - public bool TreeAST(Matcher toMatch) - { - return TreeAST((int)ESpecialNodes.eAnonymASTNode, toMatch); - } - public bool TreeAST(Creator nodeCreator, Matcher toMatch) - { - return TreeAST(nodeCreator, (int)ESpecialNodes.eAnonymASTNode, toMatch); - } - public virtual string TreeNodeToString(PegNode node) - { - return GetRuleNameFromId(node.id_); - } - public void SetNodeCreator(Creator nodeCreator) - { - Debug.Assert(nodeCreator != null); - _nodeCreator = nodeCreator; - } - #endregion Tree Node generation - #region PEG e1 e2 .. ; &e1 ; !e1 ; e? ; e* ; e+ ; e{a,b} ; . - public bool And(Matcher pegSequence) - { - var prevCur = _tree._cur; - var prevPolicy = _tree._addPolicy; - var pos0 = _pos; - var bMatches = pegSequence(); - if (!bMatches) - { - _pos = pos0; - RestoreTree(prevCur, prevPolicy); - } - return bMatches; - } - public bool Peek(Matcher toMatch) - { - var pos0 = _pos; - var prevMute = _bMute; - _bMute = true; - var bMatches = toMatch(); - _bMute = prevMute; - _pos = pos0; - return bMatches; - } - public bool Not(Matcher toMatch) - { - var pos0 = _pos; - var prevMute = _bMute; - _bMute = true; - var bMatches = toMatch(); - _bMute = prevMute; - _pos = pos0; - return !bMatches; - } - public bool PlusRepeat(Matcher toRepeat) - { - int i; - for (i = 0; ; ++i) - { - var pos0 = _pos; - if (!toRepeat()) - { - _pos = pos0; - break; - } - } - return i > 0; - } - public bool OptRepeat(Matcher toRepeat) - { - for (; ; ) - { - var pos0 = _pos; - if (!toRepeat()) - { - _pos = pos0; - return true; - } - } - } - public bool Option(Matcher toMatch) - { - var pos0 = _pos; - if (!toMatch()) _pos = pos0; - return true; - } - public bool ForRepeat(int count, Matcher toRepeat) - { - var prevCur = _tree._cur; - var prevPolicy = _tree._addPolicy; - var pos0 = _pos; - int i; - for (i = 0; i < count; ++i) - { - if (!toRepeat()) - { - _pos = pos0; - RestoreTree(prevCur, prevPolicy); - return false; - } - } - return true; - } - public bool ForRepeat(int lower, int upper, Matcher toRepeat) - { - var prevCur = _tree._cur; - var prevPolicy = _tree._addPolicy; - var pos0 = _pos; - int i; - for (i = 0; i < upper; ++i) - { - if (!toRepeat()) break; - } - if (i < lower) - { - _pos = pos0; - RestoreTree(prevCur, prevPolicy); - return false; - } - return true; - } - public bool Any() - { - if (_pos < _srcLen) - { - ++_pos; - return true; - } - return false; - } - #endregion PEG e1 e2 .. ; &e1 ; !e1 ; e? ; e* ; e+ ; e{a,b} ; . + #region Tree root access, Tree Node generation/display + public PegNode GetRoot() + { + return _tree._root; + } + + public void ResetTree() + { + _tree._root = null; + _tree._cur = null; + _tree._addPolicy = PegTree.AddPolicy.eAddAsChild; + } + + private void AddTreeNode(int nId, PegTree.AddPolicy newAddPolicy, Creator createNode, ECreatorPhase ePhase) + { + if (_bMute) + return; + if (_tree._root == null) + { + _tree._root = _tree._cur = createNode(ePhase, _tree._cur, nId); + } + else if (_tree._addPolicy == PegTree.AddPolicy.eAddAsChild) + { + _tree._cur = _tree._cur.child_ = createNode(ePhase, _tree._cur, nId); + } + else + { + _tree._cur = _tree._cur.next_ = createNode(ePhase, _tree._cur.parent_, nId); + } + _tree._addPolicy = newAddPolicy; + } + + private void RestoreTree(PegNode prevCur, PegTree.AddPolicy prevPolicy) + { + if (_bMute) + return; + if (prevCur == null) + { + _tree._root = null; + } + else if (prevPolicy == PegTree.AddPolicy.eAddAsChild) + { + prevCur.child_ = null; + } + else + { + prevCur.next_ = null; + } + _tree._cur = prevCur; + _tree._addPolicy = prevPolicy; + } + + public bool TreeChars(Matcher toMatch) + { + return TreeCharsWithId((int)ESpecialNodes.eAnonymousNode, toMatch); + } + + public bool TreeChars(Creator nodeCreator, Matcher toMatch) + { + return TreeCharsWithId(nodeCreator, (int)ESpecialNodes.eAnonymousNode, toMatch); + } + + public bool TreeCharsWithId(int nId, Matcher toMatch) + { + return TreeCharsWithId(_nodeCreator, nId, toMatch); + } + + public bool TreeCharsWithId(Creator nodeCreator, int nId, Matcher toMatch) + { + var pos = _pos; + if (toMatch()) + { + if (!_bMute) + { + AddTreeNode(nId, PegTree.AddPolicy.eAddAsSibling, nodeCreator, ECreatorPhase.eCreateAndComplete); + _tree._cur.match_._posBeg = pos; + _tree._cur.match_._posEnd = _pos; + } + return true; + } + return false; + } + + public bool TreeNT(int nRuleId, Matcher toMatch) + { + return TreeNT(_nodeCreator, nRuleId, toMatch); + } + + public bool TreeNT(Creator nodeCreator, int nRuleId, Matcher toMatch) + { + if (_bMute) + return toMatch(); + var prevCur = _tree._cur; + var prevPolicy = _tree._addPolicy; + var posBeg = _pos; + AddTreeNode(nRuleId, PegTree.AddPolicy.eAddAsChild, nodeCreator, ECreatorPhase.eCreate); + var ruleNode = _tree._cur; + var bMatches = toMatch(); + if (!bMatches) + RestoreTree(prevCur, prevPolicy); + else + { + ruleNode.match_._posBeg = posBeg; + ruleNode.match_._posEnd = _pos; + _tree._cur = ruleNode; + _tree._addPolicy = PegTree.AddPolicy.eAddAsSibling; + nodeCreator(ECreatorPhase.eCreationComplete, ruleNode, nRuleId); + } + return bMatches; + } + + public bool TreeAST(int nRuleId, Matcher toMatch) + { + return TreeAST(_nodeCreator, nRuleId, toMatch); + } + + public bool TreeAST(Creator nodeCreator, int nRuleId, Matcher toMatch) + { + if (_bMute) + return toMatch(); + var bMatches = TreeNT(nodeCreator, nRuleId, toMatch); + if (bMatches) + { + if (_tree._cur.child_ != null && _tree._cur.child_.next_ == null && _tree._cur.parent_ != null) + { + if (_tree._cur.parent_.child_ == _tree._cur) + { + _tree._cur.parent_.child_ = _tree._cur.child_; + _tree._cur.child_.parent_ = _tree._cur.parent_; + _tree._cur = _tree._cur.child_; + } + else + { + PegNode prev; + for ( + prev = _tree._cur.parent_.child_; + prev != null && prev.next_ != _tree._cur; + prev = prev.next_ + ) { } + if (prev != null) + { + prev.next_ = _tree._cur.child_; + _tree._cur.child_.parent_ = _tree._cur.parent_; + _tree._cur = _tree._cur.child_; + } + } + } + } + return bMatches; + } + + public bool TreeNT(Matcher toMatch) + { + return TreeNT((int)ESpecialNodes.eAnonymNTNode, toMatch); + } + + public bool TreeNT(Creator nodeCreator, Matcher toMatch) + { + return TreeNT(nodeCreator, (int)ESpecialNodes.eAnonymNTNode, toMatch); + } + + public bool TreeAST(Matcher toMatch) + { + return TreeAST((int)ESpecialNodes.eAnonymASTNode, toMatch); + } + + public bool TreeAST(Creator nodeCreator, Matcher toMatch) + { + return TreeAST(nodeCreator, (int)ESpecialNodes.eAnonymASTNode, toMatch); + } + + public virtual string TreeNodeToString(PegNode node) + { + return GetRuleNameFromId(node.id_); + } + + public void SetNodeCreator(Creator nodeCreator) + { + Debug.Assert(nodeCreator != null); + _nodeCreator = nodeCreator; + } + #endregion Tree Node generation + #region PEG e1 e2 .. ; &e1 ; !e1 ; e? ; e* ; e+ ; e{a,b} ; . + public bool And(Matcher pegSequence) + { + var prevCur = _tree._cur; + var prevPolicy = _tree._addPolicy; + var pos0 = _pos; + var bMatches = pegSequence(); + if (!bMatches) + { + _pos = pos0; + RestoreTree(prevCur, prevPolicy); + } + return bMatches; + } + + public bool Peek(Matcher toMatch) + { + var pos0 = _pos; + var prevMute = _bMute; + _bMute = true; + var bMatches = toMatch(); + _bMute = prevMute; + _pos = pos0; + return bMatches; + } + + public bool Not(Matcher toMatch) + { + var pos0 = _pos; + var prevMute = _bMute; + _bMute = true; + var bMatches = toMatch(); + _bMute = prevMute; + _pos = pos0; + return !bMatches; + } + + public bool PlusRepeat(Matcher toRepeat) + { + int i; + for (i = 0; ; ++i) + { + var pos0 = _pos; + if (!toRepeat()) + { + _pos = pos0; + break; + } + } + return i > 0; + } + + public bool OptRepeat(Matcher toRepeat) + { + for (; ; ) + { + var pos0 = _pos; + if (!toRepeat()) + { + _pos = pos0; + return true; + } + } + } + + public bool Option(Matcher toMatch) + { + var pos0 = _pos; + if (!toMatch()) + _pos = pos0; + return true; + } + + public bool ForRepeat(int count, Matcher toRepeat) + { + var prevCur = _tree._cur; + var prevPolicy = _tree._addPolicy; + var pos0 = _pos; + int i; + for (i = 0; i < count; ++i) + { + if (!toRepeat()) + { + _pos = pos0; + RestoreTree(prevCur, prevPolicy); + return false; + } + } + return true; + } + + public bool ForRepeat(int lower, int upper, Matcher toRepeat) + { + var prevCur = _tree._cur; + var prevPolicy = _tree._addPolicy; + var pos0 = _pos; + int i; + for (i = 0; i < upper; ++i) + { + if (!toRepeat()) + break; + } + if (i < lower) + { + _pos = pos0; + RestoreTree(prevCur, prevPolicy); + return false; + } + return true; + } + + public bool Any() + { + if (_pos < _srcLen) + { + ++_pos; + return true; + } + return false; + } + #endregion PEG e1 e2 .. ; &e1 ; !e1 ; e? ; e* ; e+ ; e{a,b} ; . } + public class PegByteParser : PegBaseParser { #region Data members @@ -806,31 +942,42 @@ public sealed class BytesetData { public struct Range { - public Range(byte low, byte high) { this.low = low; this.high = high; } + public Range(byte low, byte high) + { + this.low = low; + this.high = high; + } + public byte low; public byte high; } private readonly System.Collections.BitArray charSet_; private readonly bool bNegated_; + public BytesetData(System.Collections.BitArray b) - : this(b, false) - { - } + : this(b, false) { } + public BytesetData(System.Collections.BitArray b, bool bNegated) { charSet_ = new System.Collections.BitArray(b); bNegated_ = bNegated; } + public BytesetData(Range[] r, byte[] c) - : this(r, c, false) - { - } + : this(r, c, false) { } + public BytesetData(Range[] r, byte[] c, bool bNegated) { var max = 0; - if (r != null) foreach (var val in r) if (val.high > max) max = val.high; - if (c != null) foreach (int val in c) if (val > max) max = val; + if (r != null) + foreach (var val in r) + if (val.high > max) + max = val.high; + if (c != null) + foreach (int val in c) + if (val > max) + max = val; charSet_ = new System.Collections.BitArray(max + 1, false); if (r != null) { @@ -842,14 +989,19 @@ public BytesetData(Range[] r, byte[] c, bool bNegated) } } } - if (c != null) foreach (int val in c) charSet_[val] = true; + if (c != null) + foreach (int val in c) + charSet_[val] = true; bNegated_ = bNegated; } + public bool Matches(byte c) { var bMatches = c < charSet_.Length && charSet_[c]; - if (bNegated_) return !bMatches; - else return bMatches; + if (bNegated_) + return !bMatches; + else + return bMatches; } } /* public class BytesetData @@ -902,14 +1054,16 @@ public bool Matches(byte c) #endregion PEG optimizations #region Constructors public PegByteParser() - : this(null) - { - } - public PegByteParser(byte[] src):base(null) + : this(null) { } + + public PegByteParser(byte[] src) + : base(null) { SetSource(src); } - public PegByteParser(byte[] src, TextWriter errOut):base(errOut) + + public PegByteParser(byte[] src, TextWriter errOut) + : base(errOut) { SetSource(src); } @@ -920,26 +1074,33 @@ public void Construct(byte[] src, TextWriter fOut) base.Construct(fOut); SetSource(src); } + public void SetSource(byte[] src) { src ??= Array.Empty(); - _src = src; _srcLen = src.Length; + _src = src; + _srcLen = src.Length; _errors._lineStarts = new SortedList(); _errors._lineStarts[0] = 1; } - public byte[] GetSource() { return _src; } + + public byte[] GetSource() + { + return _src; + } #endregion Reinitialization, Source Code access, TextWriter access,Tree Access #region Setting host variables - public bool Into(Matcher toMatch,out byte[] into) + public bool Into(Matcher toMatch, out byte[] into) { var pos = _pos; if (toMatch()) { var nLen = _pos - pos; - into= new byte[nLen]; - for(var i=0;i{1}:{2}", _pos, sErrKind, sMsg); _errOut.Flush(); } + public virtual bool Fatal(string sMsg) { - LogOutMsg("FATAL", sMsg); throw new PegException(); } + public bool Warning(string sMsg) { LogOutMsg("WARNING", sMsg); return true; } #endregion Error handling - #region PEG Bit level equivalents for PEG e1 ; &e1 ; !e1; e1:into ; + #region PEG Bit level equivalents for PEG e1 ; &e1 ; !e1; e1:into ; public bool Bits(int lowBitNo, int highBitNo, byte toMatch) { if (_pos < _srcLen && ((_src[_pos] >> (lowBitNo - 1)) & ((1 << highBitNo) - 1)) == toMatch) @@ -1030,44 +1200,53 @@ public bool Bits(int lowBitNo, int highBitNo, byte toMatch) } return false; } - public bool Bits(int lowBitNo, int highBitNo,BytesetData toMatch) + + public bool Bits(int lowBitNo, int highBitNo, BytesetData toMatch) { - if( _pos < _srcLen ) + if (_pos < _srcLen) { - var value= (byte)((_src[_pos] >> (lowBitNo - 1)) & ((1 << highBitNo) - 1)); + var value = (byte)((_src[_pos] >> (lowBitNo - 1)) & ((1 << highBitNo) - 1)); ++_pos; return toMatch.Matches(value); } return false; } + public bool PeekBits(int lowBitNo, int highBitNo, byte toMatch) { return _pos < _srcLen && ((_src[_pos] >> (lowBitNo - 1)) & ((1 << highBitNo) - 1)) == toMatch; } + public bool NotBits(int lowBitNo, int highBitNo, byte toMatch) { return !(_pos < _srcLen && ((_src[_pos] >> (lowBitNo - 1)) & ((1 << highBitNo) - 1)) == toMatch); } - public bool IntoBits(int lowBitNo,int highBitNo,out int val) + + public bool IntoBits(int lowBitNo, int highBitNo, out int val) { - return BitsInto(lowBitNo,highBitNo,out val); + return BitsInto(lowBitNo, highBitNo, out val); } + public bool IntoBits(int lowBitNo, int highBitNo, BytesetData toMatch, out int val) { return BitsInto(lowBitNo, highBitNo, out val); } - public bool Bit(int bitNo,byte toMatch) + + public bool Bit(int bitNo, byte toMatch) { - if (_pos < _srcLen && ((_src[_pos]>>(bitNo-1))&1)==toMatch){ + if (_pos < _srcLen && ((_src[_pos] >> (bitNo - 1)) & 1) == toMatch) + { ++_pos; return true; } return false; } + public bool PeekBit(int bitNo, byte toMatch) { return _pos < _srcLen && ((_src[_pos] >> (bitNo - 1)) & 1) == toMatch; } + public bool NotBit(int bitNo, byte toMatch) { return !(_pos < _srcLen && ((_src[_pos] >> (bitNo - 1)) & 1) == toMatch); @@ -1077,75 +1256,107 @@ public bool NotBit(int bitNo, byte toMatch) public bool Char(byte c1) { if (_pos < _srcLen && _src[_pos] == c1) - { ++_pos; return true; } + { + ++_pos; + return true; + } return false; } + public bool Char(byte c1, byte c2) { - if (_pos + 1 < _srcLen - && _src[_pos] == c1 - && _src[_pos + 1] == c2) - { _pos += 2; return true; } + if (_pos + 1 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2) + { + _pos += 2; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3) { - if (_pos + 2 < _srcLen - && _src[_pos] == c1 - && _src[_pos + 1] == c2 - && _src[_pos + 2] == c3) - { _pos += 3; return true; } + if (_pos + 2 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3) + { + _pos += 3; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3, byte c4) { - if (_pos + 3 < _srcLen + if ( + _pos + 3 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 - && _src[_pos + 3] == c4) - { _pos += 4; return true; } + && _src[_pos + 3] == c4 + ) + { + _pos += 4; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3, byte c4, byte c5) { - if (_pos + 4 < _srcLen + if ( + _pos + 4 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 - && _src[_pos + 4] == c5) - { _pos += 5; return true; } + && _src[_pos + 4] == c5 + ) + { + _pos += 5; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6) { - if (_pos + 5 < _srcLen + if ( + _pos + 5 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 && _src[_pos + 4] == c5 - && _src[_pos + 5] == c6) - { _pos += 6; return true; } + && _src[_pos + 5] == c6 + ) + { + _pos += 6; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7) { - if (_pos + 6 < _srcLen + if ( + _pos + 6 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 && _src[_pos + 4] == c5 && _src[_pos + 5] == c6 - && _src[_pos + 6] == c7) - { _pos += 7; return true; } + && _src[_pos + 6] == c7 + ) + { + _pos += 7; + return true; + } return false; } + public bool Char(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7, byte c8) { - if (_pos + 7 < _srcLen + if ( + _pos + 7 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 @@ -1153,122 +1364,172 @@ public bool Char(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7, && _src[_pos + 4] == c5 && _src[_pos + 5] == c6 && _src[_pos + 6] == c7 - && _src[_pos + 7] == c8) - { _pos += 8; return true; } + && _src[_pos + 7] == c8 + ) + { + _pos += 8; + return true; + } return false; } + public bool Char(byte[] s) { var sLength = s.Length; - if (_pos + sLength > _srcLen) return false; + if (_pos + sLength > _srcLen) + return false; for (var i = 0; i < sLength; ++i) { - if (s[i] != _src[_pos + i]) return false; + if (s[i] != _src[_pos + i]) + return false; } _pos += sLength; return true; } + public static byte ToUpper(byte c) { - if (c >= 97 && c <= 122) return (byte)(c - 32); else return c; + if (c >= 97 && c <= 122) + return (byte)(c - 32); + else + return c; } + public bool IChar(byte c1) { if (_pos < _srcLen && ToUpper(_src[_pos]) == c1) - { ++_pos; return true; } + { + ++_pos; + return true; + } return false; } + public bool IChar(byte c1, byte c2) { - if (_pos + 1 < _srcLen - && ToUpper(_src[_pos]) == ToUpper(c1) - && ToUpper(_src[_pos + 1]) == ToUpper(c2)) - { _pos += 2; return true; } + if (_pos + 1 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2)) + { + _pos += 2; + return true; + } return false; } + public bool IChar(byte c1, byte c2, byte c3) { - if (_pos + 2 < _srcLen + if ( + _pos + 2 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2) - && ToUpper(_src[_pos + 2]) == ToUpper(c3)) - { _pos += 3; return true; } + && ToUpper(_src[_pos + 2]) == ToUpper(c3) + ) + { + _pos += 3; + return true; + } return false; } + public bool IChar(byte c1, byte c2, byte c3, byte c4) { - if (_pos + 3 < _srcLen + if ( + _pos + 3 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2) && ToUpper(_src[_pos + 2]) == ToUpper(c3) - && ToUpper(_src[_pos + 3]) == ToUpper(c4)) - { _pos += 4; return true; } + && ToUpper(_src[_pos + 3]) == ToUpper(c4) + ) + { + _pos += 4; + return true; + } return false; } + public bool IChar(byte c1, byte c2, byte c3, byte c4, byte c5) { - if (_pos + 4 < _srcLen + if ( + _pos + 4 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2) && ToUpper(_src[_pos + 2]) == ToUpper(c3) && ToUpper(_src[_pos + 3]) == ToUpper(c4) - && ToUpper(_src[_pos + 4]) == ToUpper(c5)) - { _pos += 5; return true; } + && ToUpper(_src[_pos + 4]) == ToUpper(c5) + ) + { + _pos += 5; + return true; + } return false; } + public bool IChar(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6) { - if (_pos + 5 < _srcLen + if ( + _pos + 5 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2) && ToUpper(_src[_pos + 2]) == ToUpper(c3) && ToUpper(_src[_pos + 3]) == ToUpper(c4) && ToUpper(_src[_pos + 4]) == ToUpper(c5) - && ToUpper(_src[_pos + 5]) == ToUpper(c6)) - { _pos += 6; return true; } + && ToUpper(_src[_pos + 5]) == ToUpper(c6) + ) + { + _pos += 6; + return true; + } return false; } + public bool IChar(byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7) { - if (_pos + 6 < _srcLen + if ( + _pos + 6 < _srcLen && ToUpper(_src[_pos]) == ToUpper(c1) && ToUpper(_src[_pos + 1]) == ToUpper(c2) && ToUpper(_src[_pos + 2]) == ToUpper(c3) && ToUpper(_src[_pos + 3]) == ToUpper(c4) && ToUpper(_src[_pos + 4]) == ToUpper(c5) && ToUpper(_src[_pos + 5]) == ToUpper(c6) - && ToUpper(_src[_pos + 6]) == ToUpper(c7)) - { _pos += 7; return true; } + && ToUpper(_src[_pos + 6]) == ToUpper(c7) + ) + { + _pos += 7; + return true; + } return false; } + public bool IChar(byte[] s) { var sLength = s.Length; - if (_pos + sLength > _srcLen) return false; + if (_pos + sLength > _srcLen) + return false; for (var i = 0; i < sLength; ++i) { - if (s[i] != ToUpper(_src[_pos + i])) return false; + if (s[i] != ToUpper(_src[_pos + i])) + return false; } _pos += sLength; return true; } + public bool In(byte c0, byte c1) { - if (_pos < _srcLen - && _src[_pos] >= c0 && _src[_pos] <= c1) + if (_pos < _srcLen && _src[_pos] >= c0 && _src[_pos] <= c1) { ++_pos; return true; } return false; } + public bool In(byte c0, byte c1, byte c2, byte c3) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3) { ++_pos; return true; @@ -1276,14 +1537,13 @@ public bool In(byte c0, byte c1, byte c2, byte c3) } return false; } + public bool In(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3 - || c >= c4 && c <= c5) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3 || c >= c4 && c <= c5) { ++_pos; return true; @@ -1291,15 +1551,13 @@ public bool In(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5) } return false; } + public bool In(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3 - || c >= c4 && c <= c5 - || c >= c6 && c <= c7) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3 || c >= c4 && c <= c5 || c >= c6 && c <= c7) { ++_pos; return true; @@ -1307,6 +1565,7 @@ public bool In(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, by } return false; } + public bool In(byte[] s) { if (_pos < _srcLen) @@ -1323,6 +1582,7 @@ public bool In(byte[] s) } return false; } + public bool NotIn(byte[] s) { if (_pos < _srcLen) @@ -1330,23 +1590,25 @@ public bool NotIn(byte[] s) var c = _src[_pos]; for (var i = 0; i < s.Length - 1; i += 2) { - if ( c >= s[i] && c <= s[i + 1] ) return false; + if (c >= s[i] && c <= s[i + 1]) + return false; } ++_pos; return true; } return false; } + public bool OneOf(byte c0, byte c1) { - if (_pos < _srcLen - && (_src[_pos] == c0 || _src[_pos] == c1)) + if (_pos < _srcLen && (_src[_pos] == c0 || _src[_pos] == c1)) { ++_pos; return true; } return false; } + public bool OneOf(byte c0, byte c1, byte c2) { if (_pos < _srcLen) @@ -1360,6 +1622,7 @@ public bool OneOf(byte c0, byte c1, byte c2) } return false; } + public bool OneOf(byte c0, byte c1, byte c2, byte c3) { if (_pos < _srcLen) @@ -1373,6 +1636,7 @@ public bool OneOf(byte c0, byte c1, byte c2, byte c3) } return false; } + public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4) { if (_pos < _srcLen) @@ -1386,6 +1650,7 @@ public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4) } return false; } + public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5) { if (_pos < _srcLen) @@ -1399,6 +1664,7 @@ public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5) } return false; } + public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6) { if (_pos < _srcLen) @@ -1412,6 +1678,7 @@ public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6) } return false; } + public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, byte c7) { if (_pos < _srcLen) @@ -1425,6 +1692,7 @@ public bool OneOf(byte c0, byte c1, byte c2, byte c3, byte c4, byte c5, byte c6, } return false; } + public bool OneOf(byte[] s) { if (_pos < _srcLen) @@ -1432,11 +1700,16 @@ public bool OneOf(byte[] s) var c = _src[_pos]; for (var i = 0; i < s.Length; ++i) { - if (c == s[i]) { ++_pos; return true; } + if (c == s[i]) + { + ++_pos; + return true; + } } } return false; } + public bool NotOneOf(byte[] s) { if (_pos < _srcLen) @@ -1444,22 +1717,28 @@ public bool NotOneOf(byte[] s) var c = _src[_pos]; for (var i = 0; i < s.Length; ++i) { - if (c == s[i]) { return false; } + if (c == s[i]) + { + return false; + } } return true; } return false; } + public bool OneOf(BytesetData bset) { - if(_pos < _srcLen && bset.Matches(_src[_pos])) + if (_pos < _srcLen && bset.Matches(_src[_pos])) { - ++_pos; return true; + ++_pos; + return true; } return false; } #endregion PEG '' / ''/i / [low1-high1,low2-high2..] / [] } + public class PegCharParser : PegBaseParser { #region Data members @@ -1471,31 +1750,42 @@ public sealed class OptimizedCharset { public struct Range { - public Range(char low, char high) { this.low = low; this.high = high; } + public Range(char low, char high) + { + this.low = low; + this.high = high; + } + public char low; public char high; } private readonly System.Collections.BitArray charSet_; private readonly bool bNegated_; + public OptimizedCharset(System.Collections.BitArray b) - : this(b, false) - { - } + : this(b, false) { } + public OptimizedCharset(System.Collections.BitArray b, bool bNegated) { charSet_ = new System.Collections.BitArray(b); bNegated_ = bNegated; } + public OptimizedCharset(Range[] r, char[] c) - : this(r, c, false) - { - } + : this(r, c, false) { } + public OptimizedCharset(Range[] r, char[] c, bool bNegated) { var max = 0; - if (r != null) foreach (var val in r) if (val.high > max) max = val.high; - if (c != null) foreach (int val in c) if (val > max) max = val; + if (r != null) + foreach (var val in r) + if (val.high > max) + max = val.high; + if (c != null) + foreach (int val in c) + if (val > max) + max = val; charSet_ = new System.Collections.BitArray(max + 1, false); if (r != null) { @@ -1507,23 +1797,27 @@ public OptimizedCharset(Range[] r, char[] c, bool bNegated) } } } - if (c != null) foreach (int val in c) charSet_[val] = true; + if (c != null) + foreach (int val in c) + charSet_[val] = true; bNegated_ = bNegated; } - public bool Matches(char c) { var bMatches = c < charSet_.Length && charSet_[c]; - if (bNegated_) return !bMatches; - else return bMatches; + if (bNegated_) + return !bMatches; + else + return bMatches; } } + public sealed class OptimizedLiterals { internal class Trie { - internal Trie(char cThis,int nIndex, string[] literals) + internal Trie(char cThis, int nIndex, string[] literals) { cThis_ = cThis; var cMax = char.MinValue; @@ -1532,7 +1826,8 @@ internal Trie(char cThis,int nIndex, string[] literals) foreach (var literal in literals) { - if (literal==null || nIndex > literal.Length ) continue; + if (literal == null || nIndex > literal.Length) + continue; if (nIndex == literal.Length) { bLitEnd_ = true; @@ -1540,8 +1835,10 @@ internal Trie(char cThis,int nIndex, string[] literals) } var c = literal[nIndex]; followChars.Add(c); - if ( c < cMin_) cMin_ = c; - if ( c > cMax) cMax = c; + if (c < cMin_) + cMin_ = c; + if (c > cMax) + cMax = c; } if (followChars.Count == 0) { @@ -1555,7 +1852,8 @@ internal Trie(char cThis,int nIndex, string[] literals) var subLiterals = new List(); foreach (var s in literals) { - if ( nIndex >= s.Length ) continue; + if (nIndex >= s.Length) + continue; if (c == s[nIndex]) { subLiterals.Add(s); @@ -1564,15 +1862,17 @@ internal Trie(char cThis,int nIndex, string[] literals) children_[c - cMin_] = new Trie(c, nIndex + 1, subLiterals.ToArray()); } } - } - internal char cThis_; //character stored in this node - internal bool bLitEnd_; //end of literal - internal char cMin_; //first valid character in children - internal Trie[] children_; //contains the successor node of cThis_; + internal char cThis_; //character stored in this node + internal bool bLitEnd_; //end of literal + + internal char cMin_; //first valid character in children + internal Trie[] children_; //contains the successor node of cThis_; } + internal Trie literalsRoot; + public OptimizedLiterals(string[] litAlternatives) { literalsRoot = new Trie('\u0000', 0, litAlternatives); @@ -1580,16 +1880,17 @@ public OptimizedLiterals(string[] litAlternatives) } #endregion PEG optimizations #region Constructors - public PegCharParser():this("") - { + public PegCharParser() + : this("") { } - - } - public PegCharParser(string src):base(null) + public PegCharParser(string src) + : base(null) { SetSource(src); } - public PegCharParser(string src, TextWriter errOut):base(errOut) + + public PegCharParser(string src, TextWriter errOut) + : base(errOut) { SetSource(src); _nodeCreator = DefaultNodeCreator; @@ -1602,8 +1903,10 @@ public override string TreeNodeToString(PegNode node) if (node.id_ == (int)ESpecialNodes.eAnonymousNode) { var value = node.GetAsString(_src); - if (value.Length < 32) label += " <" + value + ">"; - else label += " <" + value.Substring(0, 29) + "...>"; + if (value.Length < 32) + label += " <" + value + ">"; + else + label += " <" + value.Substring(0, 29) + "...>"; } return label; } @@ -1614,17 +1917,25 @@ public void Construct(string src, TextWriter Fout) base.Construct(Fout); SetSource(src); } + public void SetSource(string src) { - if (src == null) src = ""; - _src = src; _srcLen = src.Length; _pos = 0; + if (src == null) + src = ""; + _src = src; + _srcLen = src.Length; + _pos = 0; _errors._lineStarts = new SortedList(); _errors._lineStarts[0] = 1; } - public string GetSource() { return _src; } + + public string GetSource() + { + return _src; + } #endregion Reinitialization, Source Code access, TextWriter access,Tree Access #region Setting host variables - public bool Into(Matcher toMatch,out string into) + public bool Into(Matcher toMatch, out string into) { var pos = _pos; if (toMatch()) @@ -1638,25 +1949,32 @@ public bool Into(Matcher toMatch,out string into) return false; } } - public bool Into(Matcher toMatch,out PegBegEnd begEnd) + + public bool Into(Matcher toMatch, out PegBegEnd begEnd) { begEnd._posBeg = _pos; var bMatches = toMatch(); begEnd._posEnd = _pos; return bMatches; } - public bool Into(Matcher toMatch,out int into) + + public bool Into(Matcher toMatch, out int into) { into = 0; - if (!Into(toMatch,out string s)) return false; - if (!int.TryParse(s, out into)) return false; + if (!Into(toMatch, out string s)) + return false; + if (!int.TryParse(s, out into)) + return false; return true; } - public bool Into(Matcher toMatch,out double into) + + public bool Into(Matcher toMatch, out double into) { into = 0.0; - if (!Into(toMatch,out string s)) return false; - if (!double.TryParse(s, out into)) return false; + if (!Into(toMatch, out string s)) + return false; + if (!double.TryParse(s, out into)) + return false; return true; } #endregion Setting host variables @@ -1668,13 +1986,14 @@ private void LogOutMsg(string sErrKind, string sMsg) _errOut.WriteLine("<{0},{1},{2}>{3}:{4}", lineNo, colNo, _maxPos, sErrKind, sMsg); _errOut.Flush(); } + public virtual bool Fatal(string sMsg) { - LogOutMsg("FATAL", sMsg); throw new PegException(); //return false; } + public bool Warning(string sMsg) { LogOutMsg("WARNING", sMsg); @@ -1684,13 +2003,16 @@ public bool Warning(string sMsg) #region PEG optimized version of e* ; e+ public bool OptRepeat(OptimizedCharset charset) { - for (; _pos < _srcLen && charset.Matches(_src[_pos]); ++_pos) ; + for (; _pos < _srcLen && charset.Matches(_src[_pos]); ++_pos) + ; return true; } + public bool PlusRepeat(OptimizedCharset charset) { var pos0 = _pos; - for (; _pos < _srcLen && charset.Matches(_src[_pos]); ++_pos) ; + for (; _pos < _srcLen && charset.Matches(_src[_pos]); ++_pos) + ; return _pos > pos0; } #endregion PEG optimized version of e* ; e+ @@ -1698,75 +2020,107 @@ public bool PlusRepeat(OptimizedCharset charset) public bool Char(char c1) { if (_pos < _srcLen && _src[_pos] == c1) - { ++_pos; return true; } + { + ++_pos; + return true; + } return false; } + public bool Char(char c1, char c2) { - if (_pos + 1 < _srcLen - && _src[_pos] == c1 - && _src[_pos + 1] == c2) - { _pos += 2; return true; } + if (_pos + 1 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2) + { + _pos += 2; + return true; + } return false; } + public bool Char(char c1, char c2, char c3) { - if (_pos + 2 < _srcLen - && _src[_pos] == c1 - && _src[_pos + 1] == c2 - && _src[_pos + 2] == c3) - { _pos += 3; return true; } + if (_pos + 2 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3) + { + _pos += 3; + return true; + } return false; } + public bool Char(char c1, char c2, char c3, char c4) { - if (_pos + 3 < _srcLen + if ( + _pos + 3 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 - && _src[_pos + 3] == c4) - { _pos += 4; return true; } + && _src[_pos + 3] == c4 + ) + { + _pos += 4; + return true; + } return false; } + public bool Char(char c1, char c2, char c3, char c4, char c5) { - if (_pos + 4 < _srcLen + if ( + _pos + 4 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 - && _src[_pos + 4] == c5) - { _pos += 5; return true; } + && _src[_pos + 4] == c5 + ) + { + _pos += 5; + return true; + } return false; } + public bool Char(char c1, char c2, char c3, char c4, char c5, char c6) { - if (_pos + 5 < _srcLen + if ( + _pos + 5 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 && _src[_pos + 4] == c5 - && _src[_pos + 5] == c6) - { _pos += 6; return true; } + && _src[_pos + 5] == c6 + ) + { + _pos += 6; + return true; + } return false; } + public bool Char(char c1, char c2, char c3, char c4, char c5, char c6, char c7) { - if (_pos + 6 < _srcLen + if ( + _pos + 6 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 && _src[_pos + 3] == c4 && _src[_pos + 4] == c5 && _src[_pos + 5] == c6 - && _src[_pos + 6] == c7) - { _pos += 7; return true; } + && _src[_pos + 6] == c7 + ) + { + _pos += 7; + return true; + } return false; } + public bool Char(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8) { - if (_pos + 7 < _srcLen + if ( + _pos + 7 < _srcLen && _src[_pos] == c1 && _src[_pos + 1] == c2 && _src[_pos + 2] == c3 @@ -1774,97 +2128,147 @@ public bool Char(char c1, char c2, char c3, char c4, char c5, char c6, char c7, && _src[_pos + 4] == c5 && _src[_pos + 5] == c6 && _src[_pos + 6] == c7 - && _src[_pos + 7] == c8) - { _pos += 8; return true; } + && _src[_pos + 7] == c8 + ) + { + _pos += 8; + return true; + } return false; } + public bool Char(string s) { var sLength = s.Length; - if (_pos + sLength > _srcLen) return false; + if (_pos + sLength > _srcLen) + return false; for (var i = 0; i < sLength; ++i) { - if (s[i] != _src[_pos + i]) return false; + if (s[i] != _src[_pos + i]) + return false; } _pos += sLength; return true; } + public bool IChar(char c1) { if (_pos < _srcLen && char.ToUpper(_src[_pos]) == c1) - { ++_pos; return true; } + { + ++_pos; + return true; + } return false; } + public bool IChar(char c1, char c2) { - if (_pos + 1 < _srcLen + if ( + _pos + 1 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) - && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2)) - { _pos += 2; return true; } + && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) + ) + { + _pos += 2; + return true; + } return false; } + public bool IChar(char c1, char c2, char c3) { - if (_pos + 2 < _srcLen + if ( + _pos + 2 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) - && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3)) - { _pos += 3; return true; } + && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3) + ) + { + _pos += 3; + return true; + } return false; } + public bool IChar(char c1, char c2, char c3, char c4) { - if (_pos + 3 < _srcLen + if ( + _pos + 3 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3) - && char.ToUpper(_src[_pos + 3]) == char.ToUpper(c4)) - { _pos += 4; return true; } + && char.ToUpper(_src[_pos + 3]) == char.ToUpper(c4) + ) + { + _pos += 4; + return true; + } return false; } + public bool IChar(char c1, char c2, char c3, char c4, char c5) { - if (_pos + 4 < _srcLen + if ( + _pos + 4 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3) && char.ToUpper(_src[_pos + 3]) == char.ToUpper(c4) - && char.ToUpper(_src[_pos + 4]) == char.ToUpper(c5)) - { _pos += 5; return true; } + && char.ToUpper(_src[_pos + 4]) == char.ToUpper(c5) + ) + { + _pos += 5; + return true; + } return false; } + public bool IChar(char c1, char c2, char c3, char c4, char c5, char c6) { - if (_pos + 5 < _srcLen + if ( + _pos + 5 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3) && char.ToUpper(_src[_pos + 3]) == char.ToUpper(c4) && char.ToUpper(_src[_pos + 4]) == char.ToUpper(c5) - && char.ToUpper(_src[_pos + 5]) == char.ToUpper(c6)) - { _pos += 6; return true; } + && char.ToUpper(_src[_pos + 5]) == char.ToUpper(c6) + ) + { + _pos += 6; + return true; + } return false; } + public bool IChar(char c1, char c2, char c3, char c4, char c5, char c6, char c7) { - if (_pos + 6 < _srcLen + if ( + _pos + 6 < _srcLen && char.ToUpper(_src[_pos]) == char.ToUpper(c1) && char.ToUpper(_src[_pos + 1]) == char.ToUpper(c2) && char.ToUpper(_src[_pos + 2]) == char.ToUpper(c3) && char.ToUpper(_src[_pos + 3]) == char.ToUpper(c4) && char.ToUpper(_src[_pos + 4]) == char.ToUpper(c5) && char.ToUpper(_src[_pos + 5]) == char.ToUpper(c6) - && char.ToUpper(_src[_pos + 6]) == char.ToUpper(c7)) - { _pos += 7; return true; } + && char.ToUpper(_src[_pos + 6]) == char.ToUpper(c7) + ) + { + _pos += 7; + return true; + } return false; } + public bool IChar(string s) { var sLength = s.Length; - if (_pos + sLength > _srcLen) return false; + if (_pos + sLength > _srcLen) + return false; for (var i = 0; i < sLength; ++i) { - if (s[i] != char.ToUpper(_src[_pos + i])) return false; + if (s[i] != char.ToUpper(_src[_pos + i])) + return false; } _pos += sLength; return true; @@ -1872,21 +2276,20 @@ public bool IChar(string s) public bool In(char c0, char c1) { - if (_pos < _srcLen - && _src[_pos] >= c0 && _src[_pos] <= c1) + if (_pos < _srcLen && _src[_pos] >= c0 && _src[_pos] <= c1) { ++_pos; return true; } return false; } + public bool In(char c0, char c1, char c2, char c3) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3) { ++_pos; return true; @@ -1894,14 +2297,13 @@ public bool In(char c0, char c1, char c2, char c3) } return false; } + public bool In(char c0, char c1, char c2, char c3, char c4, char c5) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3 - || c >= c4 && c <= c5) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3 || c >= c4 && c <= c5) { ++_pos; return true; @@ -1909,15 +2311,13 @@ public bool In(char c0, char c1, char c2, char c3, char c4, char c5) } return false; } + public bool In(char c0, char c1, char c2, char c3, char c4, char c5, char c6, char c7) { if (_pos < _srcLen) { var c = _src[_pos]; - if (c >= c0 && c <= c1 - || c >= c2 && c <= c3 - || c >= c4 && c <= c5 - || c >= c6 && c <= c7) + if (c >= c0 && c <= c1 || c >= c2 && c <= c3 || c >= c4 && c <= c5 || c >= c6 && c <= c7) { ++_pos; return true; @@ -1925,6 +2325,7 @@ public bool In(char c0, char c1, char c2, char c3, char c4, char c5, char c6, ch } return false; } + public bool In(string s) { if (_pos < _srcLen) @@ -1932,13 +2333,15 @@ public bool In(string s) var c = _src[_pos]; for (var i = 0; i < s.Length - 1; i += 2) { - if (!(c >= s[i] && c <= s[i + 1])) return false; + if (!(c >= s[i] && c <= s[i + 1])) + return false; } ++_pos; return true; } return false; } + public bool NotIn(string s) { if (_pos < _srcLen) @@ -1946,23 +2349,25 @@ public bool NotIn(string s) var c = _src[_pos]; for (var i = 0; i < s.Length - 1; i += 2) { - if ( c >= s[i] && c <= s[i + 1]) return false; + if (c >= s[i] && c <= s[i + 1]) + return false; } ++_pos; return true; } return false; } + public bool OneOf(char c0, char c1) { - if (_pos < _srcLen - && (_src[_pos] == c0 || _src[_pos] == c1)) + if (_pos < _srcLen && (_src[_pos] == c0 || _src[_pos] == c1)) { ++_pos; return true; } return false; } + public bool OneOf(char c0, char c1, char c2) { if (_pos < _srcLen) @@ -1976,6 +2381,7 @@ public bool OneOf(char c0, char c1, char c2) } return false; } + public bool OneOf(char c0, char c1, char c2, char c3) { if (_pos < _srcLen) @@ -1989,6 +2395,7 @@ public bool OneOf(char c0, char c1, char c2, char c3) } return false; } + public bool OneOf(char c0, char c1, char c2, char c3, char c4) { if (_pos < _srcLen) @@ -2002,6 +2409,7 @@ public bool OneOf(char c0, char c1, char c2, char c3, char c4) } return false; } + public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5) { if (_pos < _srcLen) @@ -2015,6 +2423,7 @@ public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5) } return false; } + public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5, char c6) { if (_pos < _srcLen) @@ -2028,6 +2437,7 @@ public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5, char c6) } return false; } + public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5, char c6, char c7) { if (_pos < _srcLen) @@ -2041,6 +2451,7 @@ public bool OneOf(char c0, char c1, char c2, char c3, char c4, char c5, char c6, } return false; } + public bool OneOf(string s) { if (_pos < _srcLen) @@ -2053,6 +2464,7 @@ public bool OneOf(string s) } return false; } + public bool NotOneOf(string s) { if (_pos < _srcLen) @@ -2065,36 +2477,44 @@ public bool NotOneOf(string s) } return false; } + public bool OneOf(OptimizedCharset cset) { if (_pos < _srcLen && cset.Matches(_src[_pos])) { - ++_pos; return true; + ++_pos; + return true; } return false; } + public bool OneOfLiterals(OptimizedLiterals litAlt) { var node = litAlt.literalsRoot; - var matchPos = _pos-1; - for (var pos = _pos; pos < _srcLen ; ++pos) + var matchPos = _pos - 1; + for (var pos = _pos; pos < _srcLen; ++pos) { var c = _src[pos]; - if ( node.children_==null - || c < node.cMin_ || c > node.cMin_ + node.children_.Length - 1 - || node.children_[c - node.cMin_] == null) + if ( + node.children_ == null + || c < node.cMin_ + || c > node.cMin_ + node.children_.Length - 1 + || node.children_[c - node.cMin_] == null + ) { break; } node = node.children_[c - node.cMin_]; - if (node.bLitEnd_) matchPos = pos + 1; + if (node.bLitEnd_) + matchPos = pos + 1; } if (matchPos >= _pos) { - _pos= matchPos; + _pos = matchPos; return true; } - else return false; + else + return false; } #endregion PEG '' / ''/i / [low1-high1,low2-high2..] / [] } diff --git a/Clippit/Excel/SSFormula.cs b/Clippit/Excel/SSFormula.cs index 5a45b721..f2c1574d 100644 --- a/Clippit/Excel/SSFormula.cs +++ b/Clippit/Excel/SSFormula.cs @@ -19,9 +19,7 @@ public ParseFormula(string formula) { parserResult = _parser.Formula(); } - catch (PegException) - { - } + catch (PegException) { } if (!parserResult) { _parser.Warning("Error processing " + formula); @@ -67,7 +65,10 @@ private void ReplaceRelativeCell(PegNode node, int rowOffset, int colOffset, Str text.Remove(node.match_._posBeg, node.match_.Length); text.Insert(node.match_._posBeg, Convert.ToString(rowNumber + rowOffset)); } - else if (node.id_ == (int)EExcelFormula.A1Column && _parser.GetSource().Substring(node.match_._posBeg, 1) != "$") + else if ( + node.id_ == (int)EExcelFormula.A1Column + && _parser.GetSource().Substring(node.match_._posBeg, 1) != "$" + ) { var colNumber = GetColumnNumber(_parser.GetSource().Substring(node.match_._posBeg, node.match_.Length)); text.Remove(node.match_._posBeg, node.match_.Length); @@ -79,7 +80,8 @@ private void ReplaceRelativeCell(PegNode node, int rowOffset, int colOffset, Str // Converts the column reference string to a column number (e.g. A -> 1, B -> 2) private static int GetColumnNumber(string cellReference) => - cellReference.Where(char.IsLetter) + cellReference + .Where(char.IsLetter) .Aggregate(0, (current, c) => current * 26 + Convert.ToInt32(c) - Convert.ToInt32('A') + 1); // Translates the column number to the column reference string (e.g. 1 -> A, 2-> B) diff --git a/Clippit/Excel/SmlCellFormatter.cs b/Clippit/Excel/SmlCellFormatter.cs index 25208a3c..37ac47bb 100644 --- a/Clippit/Excel/SmlCellFormatter.cs +++ b/Clippit/Excel/SmlCellFormatter.cs @@ -24,25 +24,18 @@ private class FormatConfig public string FormatCode; } - private static readonly Dictionary ExcelFormatCodeToNetFormatCodeExceptionMap = new() - { + private static readonly Dictionary ExcelFormatCodeToNetFormatCodeExceptionMap = + new() { - "# ?/?", - new FormatConfig { - CellType = CellType.Number, - FormatCode = "0.00", - } - }, - { - "# ??/??", - new FormatConfig + "# ?/?", + new FormatConfig { CellType = CellType.Number, FormatCode = "0.00" } + }, { - CellType = CellType.Number, - FormatCode = "0.00", - } - }, - }; + "# ??/??", + new FormatConfig { CellType = CellType.Number, FormatCode = "0.00" } + }, + }; // Up to four sections of format codes can be specified. The format codes, separated by semicolons, define the // formats for positive numbers, negative numbers, zero values, and text, in that order. If only two sections are @@ -79,7 +72,6 @@ public static string FormatCell(string formatCode, string value, out string colo } } return value; - } // positive, negative, zero, text // _("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_) @@ -137,14 +129,18 @@ private static string ConvertFormatCode(string formatCode) .Replace("AM/PM", "tt") .Replace("m/", "M/") .Replace("*", "") - .Replace("?", "#") - ; + .Replace("?", "#"); var withTrimmedUnderscores = UnderRegex.Replace(newFormatCode, ""); - var withTransformedCurrency = Regex.Replace(withTrimmedUnderscores, s_CurrRegex, m => m.Groups[1].Value.TrimEnd('-')); + var withTransformedCurrency = Regex.Replace( + withTrimmedUnderscores, + s_CurrRegex, + m => m.Groups[1].Value.TrimEnd('-') + ); return withTransformedCurrency; } - private static readonly string[] ValidColors = new[] { + private static readonly string[] ValidColors = new[] + { "Black", "Blue", "Cyan", @@ -159,13 +155,11 @@ private static string FormatDouble(string formatCode, double dv, out string colo { color = null; var trimmed = formatCode.Trim(); - if (trimmed.StartsWith("[") && - trimmed.Contains("]")) + if (trimmed.StartsWith("[") && trimmed.Contains("]")) { var colorLen = trimmed.IndexOf(']'); color = trimmed.Substring(1, colorLen - 1); - if (ValidColors.Contains(color) || - color.StartsWith("Color")) + if (ValidColors.Contains(color) || color.StartsWith("Color")) { if (color.StartsWith("Color")) { @@ -184,7 +178,6 @@ private static string FormatDouble(string formatCode, double dv, out string colo color = null; } - if (formatCode == "General") return dv.ToString(CultureInfo.InvariantCulture); var isDate = IsFormatCodeForDate(formatCode); @@ -239,13 +232,13 @@ private static bool IsFormatCodeForDate(string formatCode) { if (formatCode == "General") return false; - return formatCode.Contains("m") || - formatCode.Contains("d") || - formatCode.Contains("y") || - formatCode.Contains("h") || - formatCode.Contains("s") || - formatCode.Contains("AM") || - formatCode.Contains("PM"); + return formatCode.Contains("m") + || formatCode.Contains("d") + || formatCode.Contains("y") + || formatCode.Contains("h") + || formatCode.Contains("s") + || formatCode.Contains("AM") + || formatCode.Contains("PM"); } } } diff --git a/Clippit/Excel/SmlDataRetriever.cs b/Clippit/Excel/SmlDataRetriever.cs index 197f0ebf..215c46fb 100644 --- a/Clippit/Excel/SmlDataRetriever.cs +++ b/Clippit/Excel/SmlDataRetriever.cs @@ -30,8 +30,7 @@ public static XElement RetrieveSheet(SpreadsheetDocument sDoc, string sheetName) { var wbXdoc = sDoc.WorkbookPart.GetXDocument(); var sheet = wbXdoc - .Root - .Elements(S.sheets) + .Root.Elements(S.sheets) .Elements(S.sheet) .FirstOrDefault(s => (string)s.Attribute("name") == sheetName); if (sheet == null) @@ -61,7 +60,14 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, return RetrieveRange(sDoc, sheetName, leftColumn, topRow, rightColumn, bottomRow); } - public static XElement RetrieveRange(SmlDocument smlDoc, string sheetName, int leftColumn, int topRow, int rightColumn, int bottomRow) + public static XElement RetrieveRange( + SmlDocument smlDoc, + string sheetName, + int leftColumn, + int topRow, + int rightColumn, + int bottomRow + ) { using var ms = new MemoryStream(); ms.Write(smlDoc.DocumentByteArray, 0, smlDoc.DocumentByteArray.Length); @@ -69,18 +75,31 @@ public static XElement RetrieveRange(SmlDocument smlDoc, string sheetName, int l return RetrieveRange(sDoc, sheetName, leftColumn, topRow, rightColumn, bottomRow); } - public static XElement RetrieveRange(string fileName, string sheetName, int leftColumn, int topRow, int rightColumn, int bottomRow) + public static XElement RetrieveRange( + string fileName, + string sheetName, + int leftColumn, + int topRow, + int rightColumn, + int bottomRow + ) { using var sDoc = SpreadsheetDocument.Open(fileName, false); return RetrieveRange(sDoc, sheetName, leftColumn, topRow, rightColumn, bottomRow); } - public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, int leftColumn, int topRow, int rightColumn, int bottomRow) + public static XElement RetrieveRange( + SpreadsheetDocument sDoc, + string sheetName, + int leftColumn, + int topRow, + int rightColumn, + int bottomRow + ) { var wbXdoc = sDoc.WorkbookPart.GetXDocument(); var sheet = wbXdoc - .Root - .Elements(S.sheets) + .Root.Elements(S.sheets) .Elements(S.sheet) .FirstOrDefault(s => (string)s.Attribute("name") == sheetName); if (sheet == null) @@ -106,8 +125,7 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, // assemble the transform var sheetData = shXDoc - .Root - .Elements(S.sheetData) + .Root.Elements(S.sheetData) .Elements(S.row) .Select(row => { @@ -122,8 +140,7 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, if (rowNbr > bottomRow) return null; - var cells = row - .Elements(S.c) + var cells = row.Elements(S.c) .Select(cell => { var cellAddress = (string)cell.Attribute("r"); @@ -143,27 +160,27 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, { var sharedStringBeforeParsing = (string)cell.Element(S.v); if (sharedStringBeforeParsing == null) - sharedStringBeforeParsing = (string)cell.Elements(S._is).Elements(S.t).FirstOrDefault(); + sharedStringBeforeParsing = (string) + cell.Elements(S._is).Elements(S.t).FirstOrDefault(); if (sharedStringBeforeParsing == null) throw new FileFormatException("Invalid document"); if (!int.TryParse(sharedStringBeforeParsing, out var sharedStringIndex)) throw new FileFormatException("Invalid document"); XElement sharedStringElement = null; if (sharedStringTable == null) - throw new FileFormatException("Invalid spreadsheet. Shared string, but no Shared String Part."); - sharedStringElement = - sharedStringTable + throw new FileFormatException( + "Invalid spreadsheet. Shared string, but no Shared String Part." + ); + sharedStringElement = sharedStringTable .GetXDocument() - .Root - .Elements(S.si) + .Root.Elements(S.si) .Skip(sharedStringIndex) .FirstOrDefault(); if (sharedStringElement == null) - throw new FileFormatException("Invalid spreadsheet. Shared string reference not valid."); - sharedString = - sharedStringElement - .Descendants(S.t) - .StringConcatenate(e => (string)e); + throw new FileFormatException( + "Invalid spreadsheet. Shared string reference not valid." + ); + sharedString = sharedStringElement.Descendants(S.t).StringConcatenate(e => (string)e); } if (sharedString != null) @@ -176,21 +193,29 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, displayValue = SmlCellFormatter.FormatCell( (string)cellProps.Attribute("formatCode"), value, - out color); + out color + ); else displayValue = value; - var newCell1 = new XElement("Cell", + var newCell1 = new XElement( + "Cell", new XAttribute("Ref", (string)cell.Attribute("r")), new XAttribute("ColumnId", columnAddress), new XAttribute("ColumnNumber", columnIndex), - cell.Attribute("f") != null ? new XAttribute("Formula", (string)cell.Attribute("f")) : null, - cell.Attribute("s") != null ? new XAttribute("Style", (string)cell.Attribute("s")) : null, - cell.Attribute("t") != null ? new XAttribute("Type", (string)cell.Attribute("t")) : null, + cell.Attribute("f") != null + ? new XAttribute("Formula", (string)cell.Attribute("f")) + : null, + cell.Attribute("s") != null + ? new XAttribute("Style", (string)cell.Attribute("s")) + : null, + cell.Attribute("t") != null + ? new XAttribute("Type", (string)cell.Attribute("t")) + : null, cellProps, new XElement("Value", value), new XElement("DisplayValue", displayValue), color != null ? new XElement("DisplayColor", color) : null - ); + ); return newCell1; } else @@ -212,36 +237,44 @@ public static XElement RetrieveRange(SpreadsheetDocument sDoc, string sheetName, displayValue = SmlCellFormatter.FormatCell( (string)cellProps.Attribute("formatCode"), cell.Value, - out color); + out color + ); else displayValue = displayValue = SmlCellFormatter.FormatCell( "General", cell.Value, - out color); - var newCell2 = new XElement("Cell", + out color + ); + var newCell2 = new XElement( + "Cell", new XAttribute("Ref", (string)cell.Attribute("r")), new XAttribute("ColumnId", columnAddress), new XAttribute("ColumnNumber", columnIndex), typeAttr, - cell.Attribute("f") != null ? new XAttribute("Formula", (string)cell.Attribute("f")) : null, - cell.Attribute("s") != null ? new XAttribute("Style", (string)cell.Attribute("s")) : null, + cell.Attribute("f") != null + ? new XAttribute("Formula", (string)cell.Attribute("f")) + : null, + cell.Attribute("s") != null + ? new XAttribute("Style", (string)cell.Attribute("s")) + : null, cellProps, value, new XElement("DisplayValue", displayValue), - color != null ? new XElement("DisplayColor", color) : null); + color != null ? new XElement("DisplayColor", color) : null + ); return newCell2; } }); - var dataRow = new XElement("Row", + var dataRow = new XElement( + "Row", row.Attribute("r") != null ? new XAttribute("RowNumber", (int)row.Attribute("r")) : null, - cells); + cells + ); return dataRow; }); var dataProps = GetDataProps(shXDoc); - var data = new XElement("Data", - dataProps, - sheetData); + var data = new XElement("Data", dataProps, sheetData); return data; } @@ -252,7 +285,7 @@ private static void FixUpCellsThatHaveNoRAtt(XDocument shXDoc) // if there are any rows that have all cells with no r attribute, then fix them up var invalidRows = shXDoc .Descendants(S.row) - .Where(r => ! r.Elements(S.c).Any(c => c.Attribute("r") != null)) + .Where(r => !r.Elements(S.c).Any(c => c.Attribute("r") != null)) .ToList(); foreach (var row in invalidRows) @@ -269,10 +302,7 @@ private static void FixUpCellsThatHaveNoRAtt(XDocument shXDoc) // repeat iteratively until no further fixes can be made while (true) { - var invalidCells = shXDoc - .Descendants(S.c) - .Where(c => c.Attribute("r") == null) - .ToList(); + var invalidCells = shXDoc.Descendants(S.c).Where(c => c.Attribute("r") == null).ToList(); var didFixup = false; foreach (var cell in invalidCells) @@ -365,109 +395,128 @@ public static XElement RetrieveTable(SpreadsheetDocument sDoc, string tableName) FixUpCellsThatHaveNoRAtt(shXDoc); // assemble the transform - var columns = new XElement("Columns", - table.TableColumns().Select(tc => - { - var colXElement = new XElement("Column", - tc.Name != null ? new XAttribute("Name", tc.Name) : null, - tc.UniqueName != null ? new XAttribute("UniqueName", tc.UniqueName) : null, - new XAttribute("ColumnIndex", tc.ColumnIndex), - new XAttribute("Id", tc.Id), - tc.DataDxfId != null ? new XAttribute("DataDxfId", tc.DataDxfId) : null, - tc.QueryTableFieldId != null ? new XAttribute("QueryTableFieldId", tc.QueryTableFieldId) : null); - return colXElement; - })); + var columns = new XElement( + "Columns", + table + .TableColumns() + .Select(tc => + { + var colXElement = new XElement( + "Column", + tc.Name != null ? new XAttribute("Name", tc.Name) : null, + tc.UniqueName != null ? new XAttribute("UniqueName", tc.UniqueName) : null, + new XAttribute("ColumnIndex", tc.ColumnIndex), + new XAttribute("Id", tc.Id), + tc.DataDxfId != null ? new XAttribute("DataDxfId", tc.DataDxfId) : null, + tc.QueryTableFieldId != null + ? new XAttribute("QueryTableFieldId", tc.QueryTableFieldId) + : null + ); + return colXElement; + }) + ); var dataProps = GetDataProps(shXDoc); - var data = new XElement("Data", + var data = new XElement( + "Data", dataProps, - table.TableRows().Select(tr => - { - if (!int.TryParse(tr.Row.RowId, out var rowRef)) - throw new FileFormatException("Invalid spreadsheet"); - - // filter - if (rowRef < topRow || rowRef > bottomRow) - return null; - - var cellData = tr.Row.Cells().Select(tc => + table + .TableRows() + .Select(tr => { + if (!int.TryParse(tr.Row.RowId, out var rowRef)) + throw new FileFormatException("Invalid spreadsheet"); + // filter - var columnIndex = tc.ColumnIndex; - if (columnIndex < leftColumn || columnIndex > rightColumn) + if (rowRef < topRow || rowRef > bottomRow) return null; - var cellProps = GetCellProps_InTable(sDoc, styleXDoc, table, tc); - if (tc.SharedString != null) - { - string displayValue; - string color = null; - if (cellProps != null) - displayValue = SmlCellFormatter.FormatCell( - (string)cellProps.Attribute("formatCode"), - tc.SharedString, - out color); - else - displayValue = tc.SharedString; - var newCell1 = new XElement("Cell", - tc.CellElement != null ? new XAttribute("Ref", (string)tc.CellElement.Attribute("r")) : null, - tc.ColumnAddress != null ? new XAttribute("ColumnId", tc.ColumnAddress) : null, - new XAttribute("ColumnNumber", tc.ColumnIndex), - tc.Type != null ? new XAttribute("Type", "s") : null, - tc.Formula != null ? new XAttribute("Formula", tc.Formula) : null, - tc.Style != null ? new XAttribute("Style", tc.Style) : null, - cellProps, - new XElement("Value", tc.SharedString), - new XElement("DisplayValue", displayValue), - color != null ? new XElement("DisplayColor", color) : null); - return newCell1; - } - else - { - XAttribute type = null; - if (tc.Type != null) + var cellData = tr + .Row.Cells() + .Select(tc => { - if (tc.Type == "inlineStr") - type = new XAttribute("Type", "s"); + // filter + var columnIndex = tc.ColumnIndex; + if (columnIndex < leftColumn || columnIndex > rightColumn) + return null; + + var cellProps = GetCellProps_InTable(sDoc, styleXDoc, table, tc); + if (tc.SharedString != null) + { + string displayValue; + string color = null; + if (cellProps != null) + displayValue = SmlCellFormatter.FormatCell( + (string)cellProps.Attribute("formatCode"), + tc.SharedString, + out color + ); + else + displayValue = tc.SharedString; + var newCell1 = new XElement( + "Cell", + tc.CellElement != null + ? new XAttribute("Ref", (string)tc.CellElement.Attribute("r")) + : null, + tc.ColumnAddress != null ? new XAttribute("ColumnId", tc.ColumnAddress) : null, + new XAttribute("ColumnNumber", tc.ColumnIndex), + tc.Type != null ? new XAttribute("Type", "s") : null, + tc.Formula != null ? new XAttribute("Formula", tc.Formula) : null, + tc.Style != null ? new XAttribute("Style", tc.Style) : null, + cellProps, + new XElement("Value", tc.SharedString), + new XElement("DisplayValue", displayValue), + color != null ? new XElement("DisplayColor", color) : null + ); + return newCell1; + } else - type = new XAttribute("Type", tc.Type); - } - string displayValue; - string color = null; - if (cellProps != null) - displayValue = SmlCellFormatter.FormatCell( - (string)cellProps.Attribute("formatCode"), - tc.Value, - out color); - else - displayValue = SmlCellFormatter.FormatCell( - "General", - tc.Value, - out color); - var newCell = new XElement("Cell", - tc.CellElement != null ? new XAttribute("Ref", (string)tc.CellElement.Attribute("r")) : null, - tc.ColumnAddress != null ? new XAttribute("ColumnId", tc.ColumnAddress) : null, - new XAttribute("ColumnNumber", tc.ColumnIndex), - type, - tc.Formula != null ? new XAttribute("Formula", tc.Formula) : null, - tc.Style != null ? new XAttribute("Style", tc.Style) : null, - cellProps, - new XElement("Value", tc.Value), - new XElement("DisplayValue", displayValue), - color != null ? new XElement("DisplayColor", color) : null); - return newCell; - } - }); - var rowProps = GetRowProps(tr.Row.RowElement); - var newRow = new XElement("Row", - rowProps, - new XAttribute("RowNumber", tr.Row.RowId), - cellData); - return newRow; - })); + { + XAttribute type = null; + if (tc.Type != null) + { + if (tc.Type == "inlineStr") + type = new XAttribute("Type", "s"); + else + type = new XAttribute("Type", tc.Type); + } + string displayValue; + string color = null; + if (cellProps != null) + displayValue = SmlCellFormatter.FormatCell( + (string)cellProps.Attribute("formatCode"), + tc.Value, + out color + ); + else + displayValue = SmlCellFormatter.FormatCell("General", tc.Value, out color); + var newCell = new XElement( + "Cell", + tc.CellElement != null + ? new XAttribute("Ref", (string)tc.CellElement.Attribute("r")) + : null, + tc.ColumnAddress != null ? new XAttribute("ColumnId", tc.ColumnAddress) : null, + new XAttribute("ColumnNumber", tc.ColumnIndex), + type, + tc.Formula != null ? new XAttribute("Formula", tc.Formula) : null, + tc.Style != null ? new XAttribute("Style", tc.Style) : null, + cellProps, + new XElement("Value", tc.Value), + new XElement("DisplayValue", displayValue), + color != null ? new XElement("DisplayColor", color) : null + ); + return newCell; + } + }); + var rowProps = GetRowProps(tr.Row.RowElement); + var newRow = new XElement("Row", rowProps, new XAttribute("RowNumber", tr.Row.RowId), cellData); + return newRow; + }) + ); var tableProps = GetTableProps(table); - var tableXml = new XElement("Table", + var tableXml = new XElement( + "Table", tableProps, table.TableName != null ? new XAttribute("TableName", table.TableName) : null, table.DisplayName != null ? new XAttribute("DisplayName", table.DisplayName) : null, @@ -475,7 +524,8 @@ public static XElement RetrieveTable(SpreadsheetDocument sDoc, string tableName) table.HeaderRowCount != null ? new XAttribute("HeaderRowCount", table.HeaderRowCount) : null, table.TotalsRowCount != null ? new XAttribute("TotalsRowCount", table.TotalsRowCount) : null, columns, - data); + data + ); return tableXml; } @@ -496,7 +546,12 @@ public static string[] SheetNames(string fileName) public static string[] SheetNames(SpreadsheetDocument sDoc) { var workbookXDoc = sDoc.WorkbookPart.GetXDocument(); - var sheetNames = workbookXDoc.Root.Elements(S.sheets).Elements(S.sheet).Attributes("name").Select(a => (string)a).ToArray(); + var sheetNames = workbookXDoc + .Root.Elements(S.sheets) + .Elements(S.sheet) + .Attributes("name") + .Select(a => (string)a) + .ToArray(); return sheetNames; } @@ -518,7 +573,8 @@ public static string[] TableNames(SpreadsheetDocument sDoc) { var workbookXDoc = sDoc.WorkbookPart.GetXDocument(); var sheets = workbookXDoc.Root.Elements(S.sheets).Elements(S.sheet); - var tableNames = sheets.Select(sh => + var tableNames = sheets + .Select(sh => { var rId = (string)sh.Attribute(R.id); var sheetPart = sDoc.WorkbookPart.GetPartById(rId); @@ -539,8 +595,8 @@ public static string[] TableNames(SpreadsheetDocument sDoc) .ToList(); return tableNames2; }) - .SelectMany(m => m) - .ToArray(); + .SelectMany(m => m) + .ToArray(); return tableNames; } @@ -569,11 +625,13 @@ private static XElement GetDataProps(XDocument shXDoc) var mergeCells = TransformRemoveNamespace(shXDoc.Root.Element(S.mergeCells)); - var dataProps = new XElement("DataProps", + var dataProps = new XElement( + "DataProps", TransformRemoveNamespace(sheetFormatPr), TransformRemoveNamespace(shXDoc.Root.Element(S.cols)), - mergeCells); - + mergeCells + ); + if (!dataProps.HasAttributes && !dataProps.HasElements) dataProps = null; return dataProps; @@ -601,12 +659,7 @@ private static XElement GetCellProps_NotInTable(SpreadsheetDocument sDoc, XDocum if (style == null) return cellProps; - var xf = styleXDoc - .Root - .Elements(S.cellXfs) - .Elements(S.xf) - .Skip((int)style) - .FirstOrDefault(); + var xf = styleXDoc.Root.Elements(S.cellXfs).Elements(S.xf).Skip((int)style).FirstOrDefault(); var numFmtId = (int?)xf.Attribute("numFmtId"); if (numFmtId != null) @@ -616,8 +669,7 @@ private static XElement GetCellProps_NotInTable(SpreadsheetDocument sDoc, XDocum if (masterXfId != null) { var masterXf = styleXDoc - .Root - .Elements(S.cellStyleXfs) + .Root.Elements(S.cellStyleXfs) .Elements(S.xf) .Skip((int)masterXfId) .FirstOrDefault(); @@ -633,7 +685,12 @@ private static XElement GetCellProps_NotInTable(SpreadsheetDocument sDoc, XDocum return cellProps; } - private static XElement GetCellProps_InTable(SpreadsheetDocument sDoc, XDocument styleXDoc, Table table, Cell tc) + private static XElement GetCellProps_InTable( + SpreadsheetDocument sDoc, + XDocument styleXDoc, + Table table, + Cell tc + ) { var style = tc.Style; if (style == null) @@ -649,12 +706,7 @@ private static XElement GetCellProps_InTable(SpreadsheetDocument sDoc, XDocument var d = column.DataDxfId; if (d != null) { - var dataDxf = styleXDoc - .Root - .Elements(S.dxfs) - .Elements(S.dxf) - .Skip((int)d) - .FirstOrDefault(); + var dataDxf = styleXDoc.Root.Elements(S.dxfs).Elements(S.dxf).Skip((int)d).FirstOrDefault(); if (dataDxf == null) throw new FileFormatException("Invalid spreadsheet"); @@ -670,11 +722,7 @@ private static XElement GetCellProps_InTable(SpreadsheetDocument sDoc, XDocument } } - var xf = styleXDoc.Root - .Elements(S.cellXfs) - .Elements(S.xf) - .Skip((int)style) - .FirstOrDefault(); + var xf = styleXDoc.Root.Elements(S.cellXfs).Elements(S.xf).Skip((int)style).FirstOrDefault(); if (xf == null) throw new FileFormatException("Invalid spreadsheet"); @@ -687,8 +735,7 @@ private static XElement GetCellProps_InTable(SpreadsheetDocument sDoc, XDocument if (masterXfId != null) { var masterXf = styleXDoc - .Root - .Elements(S.cellStyleXfs) + .Root.Elements(S.cellStyleXfs) .Elements(S.xf) .Skip((int)masterXfId) .FirstOrDefault(); @@ -713,8 +760,7 @@ private static void AddNumFmtIdAndFormatCode(XDocument styleXDoc, XElement props props.Add(new XAttribute("numFmtId", numFmtId)); var numFmt = styleXDoc - .Root - .Elements(S.numFmts) + .Root.Elements(S.numFmts) .Elements(S.numFmt) .FirstOrDefault(z => (int)z.Attribute("numFmtId") == numFmtId); @@ -758,12 +804,7 @@ private static void AddFormattingToCellProps(XDocument styleXDoc, XElement props if (fontId != null) { - var fontElement = styleXDoc - .Root - .Elements(S.fonts) - .Elements(S.font) - .Skip((int)fontId) - .FirstOrDefault(); + var fontElement = styleXDoc.Root.Elements(S.fonts).Elements(S.font).Skip((int)fontId).FirstOrDefault(); if (fontElement != null) { var newFontElement = (XElement)TransformRemoveNamespace(fontElement); @@ -773,12 +814,7 @@ private static void AddFormattingToCellProps(XDocument styleXDoc, XElement props if (fillId != null) { - var fillElement = styleXDoc - .Root - .Elements(S.fills) - .Elements(S.fill) - .Skip((int)fillId) - .FirstOrDefault(); + var fillElement = styleXDoc.Root.Elements(S.fills).Elements(S.fill).Skip((int)fillId).FirstOrDefault(); if (fillElement != null) { var newFillElement = (XElement)TransformRemoveNamespace(fillElement); @@ -789,8 +825,7 @@ private static void AddFormattingToCellProps(XDocument styleXDoc, XElement props if (borderId != null) { var borderElement = styleXDoc - .Root - .Elements(S.borders) + .Root.Elements(S.borders) .Elements(S.border) .Skip((int)borderId) .FirstOrDefault(); @@ -820,7 +855,8 @@ private static void MoveBooleanAttribute(XElement props, XElement xf, XName attr } } - public static string[] IndexedColors = new string[] { + public static string[] IndexedColors = new string[] + { "00000000", "00FFFFFF", "00FF0000", @@ -889,7 +925,8 @@ private static void MoveBooleanAttribute(XElement props, XElement xf, XName attr "System Background", }; - private static readonly string[] FontFamilyList = new string[] { + private static readonly string[] FontFamilyList = new string[] + { "Not applicable", "Roman", "Swiss", @@ -947,18 +984,20 @@ private static void RemoveIfEmpty(XElement xElement) xElement.Remove(); } - private static object TransformRemoveNamespace(XNode node) { return node switch { null => null, - XElement element => new XElement(element.Name.LocalName, - element.Attributes() + XElement element => new XElement( + element.Name.LocalName, + element + .Attributes() .Select(a => new XAttribute(a.Name.LocalName, (string)a)) .OrderBy(a => a.Name.LocalName), - element.Nodes().Select(n => TransformRemoveNamespace(n))), - _ => node + element.Nodes().Select(n => TransformRemoveNamespace(n)) + ), + _ => node, }; } @@ -994,7 +1033,7 @@ private static string GetFormatCodeFromFmtId(int fmtId) 47 => "mmss.0", 48 => "##0.0E+0", 49 => "@", - _ => null + _ => null, }; } diff --git a/Clippit/Excel/SmlDocument.cs b/Clippit/Excel/SmlDocument.cs index a88f31f4..204e48b8 100644 --- a/Clippit/Excel/SmlDocument.cs +++ b/Clippit/Excel/SmlDocument.cs @@ -5,70 +5,65 @@ namespace Clippit.Excel; - public class SmlDocument : OpenXmlPowerToolsDocument +public class SmlDocument : OpenXmlPowerToolsDocument +{ + private const string NotSpreadsheetExceptionMessage = "The document is not a SpreadsheetML document."; + + public SmlDocument(OpenXmlPowerToolsDocument original) + : base(original) { - private const string NotSpreadsheetExceptionMessage = "The document is not a SpreadsheetML document."; - - public SmlDocument(OpenXmlPowerToolsDocument original) - : base(original) - { - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } - public SmlDocument(OpenXmlPowerToolsDocument original, bool convertToTransitional) - : base(original, convertToTransitional) - { - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + public SmlDocument(OpenXmlPowerToolsDocument original, bool convertToTransitional) + : base(original, convertToTransitional) + { + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } + + public SmlDocument(string fileName) + : base(fileName) + { + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } - public SmlDocument(string fileName) - : base(fileName) - { - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + public SmlDocument(string fileName, bool convertToTransitional) + : base(fileName, convertToTransitional) + { + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } - public SmlDocument(string fileName, bool convertToTransitional) - : base(fileName, convertToTransitional) - { - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + public SmlDocument(string fileName, byte[] byteArray) + : base(byteArray) + { + FileName = fileName; + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } - public SmlDocument(string fileName, byte[] byteArray) - : base(byteArray) - { - FileName = fileName; - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + public SmlDocument(string fileName, byte[] byteArray, bool convertToTransitional) + : base(byteArray, convertToTransitional) + { + FileName = fileName; + if (GetDocumentType() != typeof(SpreadsheetDocument)) + throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); + } - public SmlDocument(string fileName, byte[] byteArray, bool convertToTransitional) - : base(byteArray, convertToTransitional) - { - FileName = fileName; - if (GetDocumentType() != typeof(SpreadsheetDocument)) - throw new PowerToolsDocumentException(NotSpreadsheetExceptionMessage); - } + public SmlDocument(string fileName, MemoryStream memStream) + : base(fileName, memStream) { } - public SmlDocument(string fileName, MemoryStream memStream) - : base(fileName, memStream) - { - } + public SmlDocument(string fileName, MemoryStream memStream, bool convertToTransitional) + : base(fileName, memStream, convertToTransitional) { } - public SmlDocument(string fileName, MemoryStream memStream, bool convertToTransitional) - : base(fileName, memStream, convertToTransitional) - { - } - - - [SuppressMessage("ReSharper", "UnusedMember.Global")] - public XElement ConvertToHtml(SmlToHtmlConverterSettings htmlConverterSettings, string tableName) => - SmlToHtmlConverter.ConvertTableToHtml(this, htmlConverterSettings, tableName); + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public XElement ConvertToHtml(SmlToHtmlConverterSettings htmlConverterSettings, string tableName) => + SmlToHtmlConverter.ConvertTableToHtml(this, htmlConverterSettings, tableName); - [SuppressMessage("ReSharper", "UnusedMember.Global")] - public XElement ConvertTableToHtml(string tableName) => - SmlToHtmlConverter.ConvertTableToHtml(this, new SmlToHtmlConverterSettings(), tableName); - } + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public XElement ConvertTableToHtml(string tableName) => + SmlToHtmlConverter.ConvertTableToHtml(this, new SmlToHtmlConverterSettings(), tableName); +} diff --git a/Clippit/Excel/SmlToHtmlConverter.cs b/Clippit/Excel/SmlToHtmlConverter.cs index 06b61454..4e1b1042 100644 --- a/Clippit/Excel/SmlToHtmlConverter.cs +++ b/Clippit/Excel/SmlToHtmlConverter.cs @@ -45,7 +45,11 @@ public static class SmlToHtmlConverter { // *********************************************************************************************************************************** #region PublicApis - public static XElement ConvertTableToHtml(SmlDocument smlDoc, SmlToHtmlConverterSettings settings, string tableName) + public static XElement ConvertTableToHtml( + SmlDocument smlDoc, + SmlToHtmlConverterSettings settings, + string tableName + ) { using var ms = new MemoryStream(); ms.Write(smlDoc.DocumentByteArray, 0, smlDoc.DocumentByteArray.Length); @@ -55,7 +59,11 @@ public static XElement ConvertTableToHtml(SmlDocument smlDoc, SmlToHtmlConverter return xhtml; } - public static XElement ConvertTableToHtml(SpreadsheetDocument sDoc, SmlToHtmlConverterSettings settings, string tableName) + public static XElement ConvertTableToHtml( + SpreadsheetDocument sDoc, + SmlToHtmlConverterSettings settings, + string tableName + ) { var rangeXml = SmlDataRetriever.RetrieveTable(sDoc, tableName); var xhtml = ConvertToHtmlInternal(sDoc, settings, rangeXml); @@ -64,7 +72,11 @@ public static XElement ConvertTableToHtml(SpreadsheetDocument sDoc, SmlToHtmlCon #endregion // *********************************************************************************************************************************** - private static XElement ConvertToHtmlInternal(SpreadsheetDocument sDoc, SmlToHtmlConverterSettings htmlConverterSettings, XElement rangeXml) + private static XElement ConvertToHtmlInternal( + SpreadsheetDocument sDoc, + SmlToHtmlConverterSettings htmlConverterSettings, + XElement rangeXml + ) { var xhtml = (XElement)ConvertToHtmlTransform(sDoc, htmlConverterSettings, rangeXml); @@ -81,14 +93,20 @@ private static XElement ConvertToHtmlInternal(SpreadsheetDocument sDoc, SmlToHtm return xhtml; } - private static XNode ConvertToHtmlTransform(SpreadsheetDocument sDoc, SmlToHtmlConverterSettings htmlConverterSettings, XNode node) + private static XNode ConvertToHtmlTransform( + SpreadsheetDocument sDoc, + SmlToHtmlConverterSettings htmlConverterSettings, + XNode node + ) { var element = node as XElement; if (element != null) { - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => ConvertToHtmlTransform(sDoc, htmlConverterSettings, n))); + element.Nodes().Select(n => ConvertToHtmlTransform(sDoc, htmlConverterSettings, n)) + ); } return node; } @@ -100,19 +118,16 @@ private static void ReifyStylesAndClasses(SmlToHtmlConverterSettings htmlConvert var usedCssClassNames = new HashSet(); var elementsThatNeedClasses = xhtml .DescendantsAndSelf() - .Select(d => new - { - Element = d, - Styles = d.Annotation>(), - }) + .Select(d => new { Element = d, Styles = d.Annotation>() }) .Where(z => z.Styles != null); var augmented = elementsThatNeedClasses .Select(p => new { p.Element, p.Styles, - StylesString = p.Element.Name.LocalName + "|" + p.Styles.OrderBy(k => k.Key).Select(s => - $"{s.Key}: {s.Value};").StringConcatenate(), + StylesString = p.Element.Name.LocalName + + "|" + + p.Styles.OrderBy(k => k.Key).Select(s => $"{s.Key}: {s.Value};").StringConcatenate(), }) .GroupBy(p => p.StylesString) .ToList(); @@ -129,16 +144,17 @@ private static void ReifyStylesAndClasses(SmlToHtmlConverterSettings htmlConvert classNameToUse = htmlConverterSettings.CssClassPrefix + styles["PtStyleName"]; if (usedCssClassNames.Contains(classNameToUse)) { - classNameToUse = htmlConverterSettings.CssClassPrefix + - styles["PtStyleName"] + "-" + - classCounter.ToString().Substring(1); + classNameToUse = + htmlConverterSettings.CssClassPrefix + + styles["PtStyleName"] + + "-" + + classCounter.ToString().Substring(1); classCounter++; } } else { - classNameToUse = htmlConverterSettings.CssClassPrefix + - classCounter.ToString().Substring(1); + classNameToUse = htmlConverterSettings.CssClassPrefix + classCounter.ToString().Substring(1); classCounter++; } usedCssClassNames.Add(classNameToUse); @@ -168,8 +184,7 @@ private static void ReifyStylesAndClasses(SmlToHtmlConverterSettings htmlConvert var style = d.Annotation>(); if (style == null) continue; - var styleValue = - style + var styleValue = style .Where(p => p.Key != "PtStyleName") .OrderBy(p => p.Key) .Select(e => $"{e.Key}: {e.Value};") @@ -185,9 +200,7 @@ private static void ReifyStylesAndClasses(SmlToHtmlConverterSettings htmlConvert private static void SetStyleElementValue(XElement xhtml, string styleValue) { - var styleElement = xhtml - .Descendants(Xhtml.style) - .FirstOrDefault(); + var styleElement = xhtml.Descendants(Xhtml.style).FirstOrDefault(); if (styleElement != null) styleElement.Value = styleValue; else @@ -199,47 +212,51 @@ private static void SetStyleElementValue(XElement xhtml, string styleValue) } } - private static object ConvertToHtmlTransform(WordprocessingDocument wordDoc, - WmlToHtmlConverterSettings settings, XNode node) + private static object ConvertToHtmlTransform( + WordprocessingDocument wordDoc, + WmlToHtmlConverterSettings settings, + XNode node + ) { // Ignore element. return null; } - private static readonly Dictionary FontFallback = new() - { - { "Arial", @"'{0}', 'sans-serif'" }, - { "Arial Narrow", @"'{0}', 'sans-serif'" }, - { "Arial Rounded MT Bold", @"'{0}', 'sans-serif'" }, - { "Arial Unicode MS", @"'{0}', 'sans-serif'" }, - { "Baskerville Old Face", @"'{0}', 'serif'" }, - { "Berlin Sans FB", @"'{0}', 'sans-serif'" }, - { "Berlin Sans FB Demi", @"'{0}', 'sans-serif'" }, - { "Calibri Light", @"'{0}', 'sans-serif'" }, - { "Gill Sans MT", @"'{0}', 'sans-serif'" }, - { "Gill Sans MT Condensed", @"'{0}', 'sans-serif'" }, - { "Lucida Sans", @"'{0}', 'sans-serif'" }, - { "Lucida Sans Unicode", @"'{0}', 'sans-serif'" }, - { "Segoe UI", @"'{0}', 'sans-serif'" }, - { "Segoe UI Light", @"'{0}', 'sans-serif'" }, - { "Segoe UI Semibold", @"'{0}', 'sans-serif'" }, - { "Tahoma", @"'{0}', 'sans-serif'" }, - { "Trebuchet MS", @"'{0}', 'sans-serif'" }, - { "Verdana", @"'{0}', 'sans-serif'" }, - { "Book Antiqua", @"'{0}', 'serif'" }, - { "Bookman Old Style", @"'{0}', 'serif'" }, - { "Californian FB", @"'{0}', 'serif'" }, - { "Cambria", @"'{0}', 'serif'" }, - { "Constantia", @"'{0}', 'serif'" }, - { "Garamond", @"'{0}', 'serif'" }, - { "Lucida Bright", @"'{0}', 'serif'" }, - { "Lucida Fax", @"'{0}', 'serif'" }, - { "Palatino Linotype", @"'{0}', 'serif'" }, - { "Times New Roman", @"'{0}', 'serif'" }, - { "Wide Latin", @"'{0}', 'serif'" }, - { "Courier New", @"'{0}'" }, - { "Lucida Console", @"'{0}'" }, - }; + private static readonly Dictionary FontFallback = + new() + { + { "Arial", @"'{0}', 'sans-serif'" }, + { "Arial Narrow", @"'{0}', 'sans-serif'" }, + { "Arial Rounded MT Bold", @"'{0}', 'sans-serif'" }, + { "Arial Unicode MS", @"'{0}', 'sans-serif'" }, + { "Baskerville Old Face", @"'{0}', 'serif'" }, + { "Berlin Sans FB", @"'{0}', 'sans-serif'" }, + { "Berlin Sans FB Demi", @"'{0}', 'sans-serif'" }, + { "Calibri Light", @"'{0}', 'sans-serif'" }, + { "Gill Sans MT", @"'{0}', 'sans-serif'" }, + { "Gill Sans MT Condensed", @"'{0}', 'sans-serif'" }, + { "Lucida Sans", @"'{0}', 'sans-serif'" }, + { "Lucida Sans Unicode", @"'{0}', 'sans-serif'" }, + { "Segoe UI", @"'{0}', 'sans-serif'" }, + { "Segoe UI Light", @"'{0}', 'sans-serif'" }, + { "Segoe UI Semibold", @"'{0}', 'sans-serif'" }, + { "Tahoma", @"'{0}', 'sans-serif'" }, + { "Trebuchet MS", @"'{0}', 'sans-serif'" }, + { "Verdana", @"'{0}', 'sans-serif'" }, + { "Book Antiqua", @"'{0}', 'serif'" }, + { "Bookman Old Style", @"'{0}', 'serif'" }, + { "Californian FB", @"'{0}', 'serif'" }, + { "Cambria", @"'{0}', 'serif'" }, + { "Constantia", @"'{0}', 'serif'" }, + { "Garamond", @"'{0}', 'serif'" }, + { "Lucida Bright", @"'{0}', 'serif'" }, + { "Lucida Fax", @"'{0}', 'serif'" }, + { "Palatino Linotype", @"'{0}', 'serif'" }, + { "Times New Roman", @"'{0}', 'serif'" }, + { "Wide Latin", @"'{0}', 'serif'" }, + { "Courier New", @"'{0}'" }, + { "Lucida Console", @"'{0}'" }, + }; private static void CreateFontCssProperty(string font, Dictionary style) { @@ -264,7 +281,7 @@ private static bool GetBoolProp(XElement runProps, XName xName) { "0" or "false" => false, "1" or "true" => true, - _ => false + _ => false, }; } } diff --git a/Clippit/Excel/SpreadsheetDocumentManager.cs b/Clippit/Excel/SpreadsheetDocumentManager.cs index 73f595e9..8fc1ed39 100644 --- a/Clippit/Excel/SpreadsheetDocumentManager.cs +++ b/Clippit/Excel/SpreadsheetDocumentManager.cs @@ -31,7 +31,12 @@ static SpreadsheetDocumentManager() /// Contents of data /// Row to start copying data from /// - public static void Create(SpreadsheetDocument document, List headerList, string[][] valueTable, int initialRow) + public static void Create( + SpreadsheetDocument document, + List headerList, + string[][] valueTable, + int initialRow + ) { headerRow = initialRow; @@ -76,17 +81,16 @@ private static string GetSheetName(WorksheetPart worksheet, SpreadsheetDocument var partId = document.WorkbookPart.GetIdOfPart(worksheet); var workbookDocument = document.WorkbookPart.GetXDocument(); //Gets the name from sheet tag related to worksheet - var sheetName = - workbookDocument.Root - .Element(ns + "sheets") + var sheetName = workbookDocument + .Root.Element(ns + "sheets") .Elements(ns + "sheet") - .Where( - t => - t.Attribute(relationshipsns + "id").Value == partId - ).First() - .Attribute("name").Value; + .Where(t => t.Attribute(relationshipsns + "id").Value == partId) + .First() + .Attribute("name") + .Value; return sheetName; } + /// /// Gets the range reference for category /// @@ -95,18 +99,17 @@ private static string GetSheetName(WorksheetPart worksheet, SpreadsheetDocument /// column names from data /// Data values /// - private static string GetCategoryReference(string sheetName, string headerColumn, List headerList, string[][] valueTable) + private static string GetCategoryReference( + string sheetName, + string headerColumn, + List headerList, + string[][] valueTable + ) { var categoryColumn = headerList.IndexOf(headerColumn.ToUpper()) + 1; var numRows = valueTable.GetLength(0); - return GetRangeReference( - sheetName, - categoryColumn, - headerRow + 1, - categoryColumn, - numRows + headerRow - ); + return GetRangeReference(sheetName, categoryColumn, headerRow + 1, categoryColumn, numRows + headerRow); } /// @@ -118,18 +121,20 @@ private static string GetCategoryReference(string sheetName, string headerColumn /// Data values /// Columns used as data series /// - private static List GetHeaderReferences(string sheetName, string headerColumn, List headerList, List colsToChart, string[][] valueTable) + private static List GetHeaderReferences( + string sheetName, + string headerColumn, + List headerList, + List colsToChart, + string[][] valueTable + ) { var valueReferenceList = new List(); foreach (var column in colsToChart) { valueReferenceList.Add( - GetRangeReference( - sheetName, - headerList.IndexOf(column.ToUpper()) + 1, - headerRow - ) + GetRangeReference(sheetName, headerList.IndexOf(column.ToUpper()) + 1, headerRow) ); } return valueReferenceList; @@ -144,7 +149,13 @@ private static List GetHeaderReferences(string sheetName, string headerC /// Data values /// Columns used as data series /// - private static List GetValueReferences(string sheetName, string headerColumn, List headerList, List colsToChart, string[][] valueTable) + private static List GetValueReferences( + string sheetName, + string headerColumn, + List headerList, + List colsToChart, + string[][] valueTable + ) { var valueReferenceList = new List(); var numRows = valueTable.GetLength(0); @@ -153,13 +164,7 @@ private static List GetValueReferences(string sheetName, string headerCo { var dataColumn = headerList.IndexOf(column.ToUpper()) + 1; valueReferenceList.Add( - GetRangeReference( - sheetName, - dataColumn, - headerRow + 1, - dataColumn, - numRows + headerRow - ) + GetRangeReference(sheetName, dataColumn, headerRow + 1, dataColumn, numRows + headerRow) ); } return valueReferenceList; @@ -176,10 +181,15 @@ private static string GetRangeReference(string worksheet, int column, int row) /// /// Gets a formatted representation of a cell range from a worksheet /// - private static string GetRangeReference(string worksheet, int startColumn, int startRow, int endColumn, int endRow) + private static string GetRangeReference( + string worksheet, + int startColumn, + int startRow, + int endColumn, + int endRow + ) { - return - $"{worksheet}!{WorksheetAccessor.GetColumnId(startColumn)}{startRow}:{WorksheetAccessor.GetColumnId(endColumn)}{endRow}"; + return $"{worksheet}!{WorksheetAccessor.GetColumnId(startColumn)}{startRow}:{WorksheetAccessor.GetColumnId(endColumn)}{endRow}"; } /// @@ -188,14 +198,14 @@ private static string GetRangeReference(string worksheet, int startColumn, int s /// private static XDocument CreateEmptyWorkbook() { - var document = - new XDocument( - new XElement(ns + "workbook", - new XAttribute("xmlns", ns), - new XAttribute(XNamespace.Xmlns + "r", relationshipsns), - new XElement(ns + "sheets") - ) - ); + var document = new XDocument( + new XElement( + ns + "workbook", + new XAttribute("xmlns", ns), + new XAttribute(XNamespace.Xmlns + "r", relationshipsns), + new XElement(ns + "sheets") + ) + ); return document; } diff --git a/Clippit/Excel/SpreadsheetWriter.cs b/Clippit/Excel/SpreadsheetWriter.cs index 11663f07..e2da20f4 100644 --- a/Clippit/Excel/SpreadsheetWriter.cs +++ b/Clippit/Excel/SpreadsheetWriter.cs @@ -18,7 +18,7 @@ namespace Clippit.Excel // The classes in SpreadsheetWriter are still a work-in-progress. While they are useful in their current state, I will be enhancing and // changing them in the future. In particular, I will be augmenting the various definition classes (WorkbookDfn, WorksheetDfn, // RowDfn, and CellDfn. - + // They are robust enough in their current form to be used in enterprise, mission critical. public class WorkbookDfn @@ -48,36 +48,37 @@ public class RowDfn // Standard formats public class CellDfn { - public static readonly Dictionary StandardFormats = new() - { - { "0", 1 }, - { "0.00", 2 }, - { "#,##0", 3 }, - { "#,##0.00", 4 }, - { "0%", 9 }, - { "0.00%", 10 }, - { "0.00E+00", 11 }, - { "# ?/?", 12 }, - { "# ??/??", 13 }, - { "mm-dd-yy", 14 }, - { "d-mmm-yy", 15 }, - { "d-mmm", 16 }, - { "mmm-yy", 17 }, - { "h:mm AM/PM", 18 }, - { "h:mm:ss AM/PM", 19 }, - { "h:mm", 20 }, - { "h:mm:ss", 21 }, - { "h/d/yy h:mm", 22 }, - { "#,##0;(#,##0)", 37 }, - { "#,##0;[Red](#,##0)", 38 }, - { "#,##0.00;(#,##0.00)", 39 }, - { "#,##0.00;[Red](#,##0.00)", 40 }, - { "mm:ss", 45 }, - { "[h]:mm:ss", 46 }, - { "mmss.0", 47 }, - { "##0.0E+0", 48 }, - { "@", 49 }, - }; + public static readonly Dictionary StandardFormats = + new() + { + { "0", 1 }, + { "0.00", 2 }, + { "#,##0", 3 }, + { "#,##0.00", 4 }, + { "0%", 9 }, + { "0.00%", 10 }, + { "0.00E+00", 11 }, + { "# ?/?", 12 }, + { "# ??/??", 13 }, + { "mm-dd-yy", 14 }, + { "d-mmm-yy", 15 }, + { "d-mmm", 16 }, + { "mmm-yy", 17 }, + { "h:mm AM/PM", 18 }, + { "h:mm:ss AM/PM", 19 }, + { "h:mm", 20 }, + { "h:mm:ss", 21 }, + { "h/d/yy h:mm", 22 }, + { "#,##0;(#,##0)", 37 }, + { "#,##0;[Red](#,##0)", 38 }, + { "#,##0.00;(#,##0.00)", 39 }, + { "#,##0.00;[Red](#,##0.00)", 40 }, + { "mm:ss", 45 }, + { "[h]:mm:ss", 46 }, + { "mmss.0", 47 }, + { "##0.0E+0", 48 }, + { "@", 49 }, + }; public object Value { get; set; } public CellDataType? CellDataType { get; set; } public HorizontalCellAlignment? HorizontalCellAlignment { get; set; } @@ -108,8 +109,10 @@ public static void Write(string fileName, WorkbookDfn workbook) { try { - if (fileName is null) throw new ArgumentNullException(nameof(fileName)); - if (workbook is null) throw new ArgumentNullException(nameof(workbook)); + if (fileName is null) + throw new ArgumentNullException(nameof(fileName)); + if (workbook is null) + throw new ArgumentNullException(nameof(workbook)); var fi = new FileInfo(fileName); if (fi.Exists) @@ -128,12 +131,14 @@ public static void Write(string fileName, WorkbookDfn workbook) throw; } } - + public static void WriteTo(this WorkbookDfn workbook, Stream stream) { - if (stream is null) throw new ArgumentNullException(nameof(stream)); - if (workbook is null) throw new ArgumentNullException(nameof(workbook)); - + if (stream is null) + throw new ArgumentNullException(nameof(stream)); + if (workbook is null) + throw new ArgumentNullException(nameof(workbook)); + // create the blank workbook foreach (var b in CreateBlankWorkbook()) { @@ -157,13 +162,13 @@ private static void SaveWorkbookToSpreadSheet(SpreadsheetDocument sDoc, Workbook { var workbookPart = sDoc.WorkbookPart; var wXDoc = workbookPart.GetXDocument(); - var sheetElement = wXDoc.Root - .Elements(S.sheets) + var sheetElement = wXDoc + .Root.Elements(S.sheets) .Elements(S.sheet) .FirstOrDefault(s => (string)s.Attribute(SSNoNamespace.name) == "Sheet1"); if (sheetElement is null) throw new SpreadsheetWriterInternalException(); - + var id = (string)sheetElement.Attribute(R.id); sheetElement.Remove(); workbookPart.PutXDocument(); @@ -171,13 +176,8 @@ private static void SaveWorkbookToSpreadSheet(SpreadsheetDocument sDoc, Workbook var sPart = (WorksheetPart)workbookPart.GetPartById(id); workbookPart.DeletePart(sPart); - var appXDoc = sDoc - .ExtendedFilePropertiesPart - .GetXDocument(); - var vector = appXDoc.Root - .Elements(EP.TitlesOfParts) - .Elements(VT.vector) - .FirstOrDefault(); + var appXDoc = sDoc.ExtendedFilePropertiesPart.GetXDocument(); + var vector = appXDoc.Root.Elements(EP.TitlesOfParts).Elements(VT.vector).FirstOrDefault(); if (vector != null) { vector.SetAttributeValue(SSNoNamespace.size, 0); @@ -185,14 +185,8 @@ private static void SaveWorkbookToSpreadSheet(SpreadsheetDocument sDoc, Workbook lpstr.Remove(); } - var vector2 = appXDoc - .Root - .Elements(EP.HeadingPairs) - .Elements(VT.vector) - .FirstOrDefault(); - var variant = vector2 - .Descendants(VT.i4) - .FirstOrDefault(); + var vector2 = appXDoc.Root.Elements(EP.HeadingPairs).Elements(VT.vector).FirstOrDefault(); + var variant = vector2.Descendants(VT.i4).FirstOrDefault(); if (variant != null) variant.Value = "1"; sDoc.ExtendedFilePropertiesPart.PutXDocument(); @@ -215,30 +209,27 @@ public static void AddWorksheet(SpreadsheetDocument sDoc, WorksheetDfn worksheet // throw WorksheetAlreadyExistsException if a sheet with the same name (case-insensitive) already exists in the workbook var UCName = worksheetData.Name.ToUpper(); var wXDoc = sDoc.WorkbookPart.GetXDocument(); - if (wXDoc.Root - .Elements(S.sheets) - .Elements(S.sheet) - .Attributes(SSNoNamespace.name) - .Select(a => ((string)a).ToUpper()) - .Contains(UCName)) + if ( + wXDoc + .Root.Elements(S.sheets) + .Elements(S.sheet) + .Attributes(SSNoNamespace.name) + .Select(a => ((string)a).ToUpper()) + .Contains(UCName) + ) throw new WorksheetAlreadyExistsException(worksheetData.Name); // create the worksheet with the supplied name - var appXDoc = sDoc - .ExtendedFilePropertiesPart - .GetXDocument(); - var vector = appXDoc.Root - .Elements(EP.TitlesOfParts) - .Elements(VT.vector) - .FirstOrDefault(); + var appXDoc = sDoc.ExtendedFilePropertiesPart.GetXDocument(); + var vector = appXDoc.Root.Elements(EP.TitlesOfParts).Elements(VT.vector).FirstOrDefault(); if (vector != null) { var size = (int?)vector.Attribute(SSNoNamespace.size) ?? 0; size += 1; vector.SetAttributeValue(SSNoNamespace.size, size); vector.Add(new XElement(VT.lpstr, worksheetData.Name)); - var i4 = appXDoc.Root - .Elements(EP.HeadingPairs) + var i4 = appXDoc + .Root.Elements(EP.HeadingPairs) .Elements(VT.vector) .Elements(VT.variant) .Elements(VT.i4) @@ -255,10 +246,13 @@ public static void AddWorksheet(SpreadsheetDocument sDoc, WorksheetDfn worksheet var wbXDoc = workbook.GetXDocument(); var sheets = wbXDoc.Descendants(S.sheets).FirstOrDefault(); sheets.Add( - new XElement(S.sheet, + new XElement( + S.sheet, new XAttribute(SSNoNamespace.name, worksheetData.Name), new XAttribute(SSNoNamespace.sheetId, sheets.Elements(S.sheet).Count() + 1), - new XAttribute(R.id, rId))); + new XAttribute(R.id, rId) + ) + ); workbook.PutXDocument(); var ws = S.s.ToString(); @@ -279,8 +273,14 @@ public static void AddWorksheet(SpreadsheetDocument sDoc, WorksheetDfn worksheet var row = new RowDfn { Cells = worksheetData.ColumnHeadings }; SerializeRows(sDoc, partXmlWriter, new[] { row }, 1, out numColumns, out numColumnHeadingRows); } - SerializeRows(sDoc, partXmlWriter, worksheetData.Rows, numColumnHeadingRows + 1, out var numColumnsInRows, - out var numRows); + SerializeRows( + sDoc, + partXmlWriter, + worksheetData.Rows, + numColumnHeadingRows + 1, + out var numColumnsInRows, + out var numRows + ); var totalRows = numColumnHeadingRows + numRows; var totalColumns = Math.Max(numColumns, numColumnsInRows); if (worksheetData.ColumnHeadings != null && worksheetData.TableName != null) @@ -298,33 +298,52 @@ public static void AddWorksheet(SpreadsheetDocument sDoc, WorksheetDfn worksheet var tXDoc = tdp.GetXDocument(); // TODO: Optimize - var tableCount = sDoc.Parts - .SelectMany(x => x.OpenXmlPart.Parts) + var tableCount = sDoc + .Parts.SelectMany(x => x.OpenXmlPart.Parts) .SelectMany(x => x.OpenXmlPart.Parts) .Where(x => x.OpenXmlPart is TableDefinitionPart) .Select(x => x.OpenXmlPart.Uri) - .Distinct().Count(); - - var table = new XElement(S.table, + .Distinct() + .Count(); + + var table = new XElement( + S.table, new XAttribute(SSNoNamespace.id, tableCount + 1), new XAttribute(SSNoNamespace.name, worksheetData.TableName), new XAttribute(SSNoNamespace.displayName, worksheetData.TableName), - new XAttribute(SSNoNamespace._ref, "A1:" + SpreadsheetMLUtil.IntToColumnId(totalColumns - 1) + totalRows), + new XAttribute( + SSNoNamespace._ref, + "A1:" + SpreadsheetMLUtil.IntToColumnId(totalColumns - 1) + totalRows + ), new XAttribute(SSNoNamespace.totalsRowShown, 0), - new XElement(S.autoFilter, - new XAttribute(SSNoNamespace._ref, "A1:" + SpreadsheetMLUtil.IntToColumnId(totalColumns - 1) + totalRows)), - new XElement(S.tableColumns, + new XElement( + S.autoFilter, + new XAttribute( + SSNoNamespace._ref, + "A1:" + SpreadsheetMLUtil.IntToColumnId(totalColumns - 1) + totalRows + ) + ), + new XElement( + S.tableColumns, new XAttribute(SSNoNamespace.count, totalColumns), - worksheetData.ColumnHeadings.Select((ch, i) => - new XElement(S.tableColumn, - new XAttribute(SSNoNamespace.id, i + 1), - new XAttribute(SSNoNamespace.name, ch.Value)))), - new XElement(S.tableStyleInfo, + worksheetData.ColumnHeadings.Select( + (ch, i) => + new XElement( + S.tableColumn, + new XAttribute(SSNoNamespace.id, i + 1), + new XAttribute(SSNoNamespace.name, ch.Value) + ) + ) + ), + new XElement( + S.tableStyleInfo, new XAttribute(SSNoNamespace.name, "TableStyleMedium2"), new XAttribute(SSNoNamespace.showFirstColumn, 0), new XAttribute(SSNoNamespace.showLastColumn, 0), new XAttribute(SSNoNamespace.showRowStripes, 1), - new XAttribute(SSNoNamespace.showColumnStripes, 0))); + new XAttribute(SSNoNamespace.showColumnStripes, 0) + ) + ); tXDoc.Add(table); tdp.PutXDocument(); } @@ -334,8 +353,14 @@ public static void AddWorksheet(SpreadsheetDocument sDoc, WorksheetDfn worksheet sDoc.WorkbookPart.WorkbookStylesPart.Stylesheet.Save(); } - private static void SerializeRows(SpreadsheetDocument sDoc, XmlWriter xmlWriter, IEnumerable rows, - int startingRowNumber, out int numColumns, out int numRows) + private static void SerializeRows( + SpreadsheetDocument sDoc, + XmlWriter xmlWriter, + IEnumerable rows, + int startingRowNumber, + out int numColumns, + out int numRows + ) { var rowCount = 0; var rowNumber = startingRowNumber; @@ -362,7 +387,13 @@ private static void SerializeRows(SpreadsheetDocument sDoc, XmlWriter xmlWriter, numRows = rowCount; } - private static void SerializeRow(SpreadsheetDocument sDoc, XmlWriter xw, int rowCount, RowDfn row, out int numColumns) + private static void SerializeRow( + SpreadsheetDocument sDoc, + XmlWriter xw, + int rowCount, + RowDfn row, + out int numColumns + ) { var ns = S.s.NamespaceName; @@ -382,10 +413,12 @@ private static void SerializeRow(SpreadsheetDocument sDoc, XmlWriter xw, int row xw.WriteStartAttribute("r"); xw.WriteValue(SpreadsheetMLUtil.IntToColumnId(cellCount) + rowCount); xw.WriteEndAttribute(); - if (cell.Bold != null || - cell.Italic != null || - cell.FormatCode != null || - cell.HorizontalCellAlignment != null) + if ( + cell.Bold != null + || cell.Italic != null + || cell.FormatCode != null + || cell.HorizontalCellAlignment != null + ) { xw.WriteStartAttribute("s"); xw.WriteValue(GetCellStyle(sDoc, cell)); @@ -425,10 +458,10 @@ private static void SerializeRow(SpreadsheetDocument sDoc, XmlWriter xw, int row switch (cell.Value) { case DateTime dt: - xw.WriteValue(dt.ToString( "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff")); + xw.WriteValue(dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff")); break; case DateTimeOffset dts: - xw.WriteValue(dts.ToString( "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")); + xw.WriteValue(dts.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffzzz")); break; default: xw.WriteValue(cell.Value); @@ -448,14 +481,9 @@ private static int GetCellStyle(SpreadsheetDocument sDoc, CellDfn cell) { var sXDoc = sDoc.WorkbookPart.WorkbookStylesPart.GetXDocument(); var match = sXDoc - .Root - .Element(S.cellXfs) + .Root.Element(S.cellXfs) .Elements(S.xf) - .Select((e, i) => new - { - Element = e, - Index = i, - }) + .Select((e, i) => new { Element = e, Index = i }) .FirstOrDefault(xf => CompareStyles(sXDoc, xf.Element, cell)); if (match != null) return match.Index; @@ -479,8 +507,10 @@ private static int CreateNewStyle(XDocument sXDoc, CellDfn cell, SpreadsheetDocu if (cell.HorizontalCellAlignment != null) { applyAlignment = new XAttribute(SSNoNamespace.applyAlignment, 1); - alignment = new XElement(S.alignment, - new XAttribute(SSNoNamespace.horizontal, cell.HorizontalCellAlignment.ToString().ToLower())); + alignment = new XElement( + S.alignment, + new XAttribute(SSNoNamespace.horizontal, cell.HorizontalCellAlignment.ToString().ToLower()) + ); } XAttribute applyNumberFormat = null; XAttribute numFmtId = null; @@ -497,21 +527,11 @@ private static int CreateNewStyle(XDocument sXDoc, CellDfn cell, SpreadsheetDocu numFmtId = new XAttribute(SSNoNamespace.numFmtId, GetNumFmtId(sXDoc, cell.FormatCode)); } } - var newXf = new XElement(S.xf, - applyFont, - fontId, - applyAlignment, - alignment, - applyNumberFormat, - numFmtId); - var cellXfs = sXDoc - .Root - .Element(S.cellXfs); + var newXf = new XElement(S.xf, applyFont, fontId, applyAlignment, alignment, applyNumberFormat, numFmtId); + var cellXfs = sXDoc.Root.Element(S.cellXfs); if (cellXfs == null) { - cellXfs = new XElement(S.cellXfs, - new XAttribute(SSNoNamespace.count, 1), - newXf); + cellXfs = new XElement(S.cellXfs, new XAttribute(SSNoNamespace.count, 1), newXf); return 0; } else @@ -528,17 +548,23 @@ private static int GetFontId(XDocument sXDoc, CellDfn cell) var fonts = sXDoc.Root.Element(S.fonts); if (fonts == null) { - fonts = new XElement(S.fonts, + fonts = new XElement( + S.fonts, new XAttribute(SSNoNamespace.count, 1), - new XElement(S.font, + new XElement( + S.font, cell.Bold == true ? new XElement(S.b) : null, - cell.Italic == true ? new XElement(S.i) : null)); + cell.Italic == true ? new XElement(S.i) : null + ) + ); sXDoc.Root.Add(fonts); return 0; } - var font = new XElement(S.font, + var font = new XElement( + S.font, cell.Bold == true ? new XElement(S.b) : null, - cell.Italic == true ? new XElement(S.i) : null); + cell.Italic == true ? new XElement(S.i) : null + ); fonts.Add(font); var count = (int)fonts.Attribute(SSNoNamespace.count); fonts.SetAttributeValue(SSNoNamespace.count, count + 1); @@ -550,28 +576,35 @@ private static int GetNumFmtId(XDocument sXDoc, string formatCode) var xfNumber = 81; while (true) { - if (!sXDoc - .Root - .Elements(S.numFmts) - .Elements(S.numFmt) - .Any(nf => (int)nf.Attribute(SSNoNamespace.numFmtId) == xfNumber)) + if ( + !sXDoc + .Root.Elements(S.numFmts) + .Elements(S.numFmt) + .Any(nf => (int)nf.Attribute(SSNoNamespace.numFmtId) == xfNumber) + ) break; ++xfNumber; } var numFmts = sXDoc.Root.Element(S.numFmts); if (numFmts == null) { - numFmts = new XElement(S.numFmts, + numFmts = new XElement( + S.numFmts, new XAttribute(SSNoNamespace.count, 1), - new XElement(S.numFmt, + new XElement( + S.numFmt, new XAttribute(SSNoNamespace.numFmtId, xfNumber), - new XAttribute(SSNoNamespace.formatCode, formatCode))); + new XAttribute(SSNoNamespace.formatCode, formatCode) + ) + ); sXDoc.Root.AddFirst(numFmts); return xfNumber; } - var numFmt = new XElement(S.numFmt, + var numFmt = new XElement( + S.numFmt, new XAttribute(SSNoNamespace.numFmtId, xfNumber), - new XAttribute(SSNoNamespace.formatCode, formatCode)); + new XAttribute(SSNoNamespace.formatCode, formatCode) + ); numFmts.Add(numFmt); return xfNumber; } @@ -586,37 +619,36 @@ private static bool CompareStyles(XDocument sXDoc, XElement xf, CellDfn cell) private static bool MatchFont(XDocument sXDoc, XElement xf, CellDfn cell) { - if (((int?)xf.Attribute(SSNoNamespace.applyFont) == 0 || - xf.Attribute(SSNoNamespace.applyFont) == null) && - cell.Bold is null or false && - cell.Italic is null or false) + if ( + ((int?)xf.Attribute(SSNoNamespace.applyFont) == 0 || xf.Attribute(SSNoNamespace.applyFont) == null) + && cell.Bold is null or false + && cell.Italic is null or false + ) return true; - if (((int?)xf.Attribute(SSNoNamespace.applyFont) == 0 || - xf.Attribute(SSNoNamespace.applyFont) == null) && - (cell.Bold == true || - cell.Italic == true)) + if ( + ((int?)xf.Attribute(SSNoNamespace.applyFont) == 0 || xf.Attribute(SSNoNamespace.applyFont) == null) + && (cell.Bold == true || cell.Italic == true) + ) return false; var fontId = (int)xf.Attribute(SSNoNamespace.fontId); - var font = sXDoc - .Root - .Element(S.fonts) - .Elements(S.font) - .ElementAt(fontId); - var fabFont = new XElement(S.font, + var font = sXDoc.Root.Element(S.fonts).Elements(S.font).ElementAt(fontId); + var fabFont = new XElement( + S.font, cell.Bold == true ? new XElement(S.b) : null, - cell.Italic == true ? new XElement(S.i) : null); + cell.Italic == true ? new XElement(S.i) : null + ); var match = XNode.DeepEquals(font, fabFont); return match; } private static bool MatchAlignment(XDocument sXDoc, XElement xf, CellDfn cell) { - if ((int?)xf.Attribute(SSNoNamespace.applyAlignment) == 0 || - (xf.Attribute(SSNoNamespace.applyAlignment) == null) && - cell.HorizontalCellAlignment == null) + if ( + (int?)xf.Attribute(SSNoNamespace.applyAlignment) == 0 + || (xf.Attribute(SSNoNamespace.applyAlignment) == null) && cell.HorizontalCellAlignment == null + ) return true; - if (xf.Attribute(SSNoNamespace.applyAlignment) == null && - cell.HorizontalCellAlignment != null) + if (xf.Attribute(SSNoNamespace.applyAlignment) == null && cell.HorizontalCellAlignment != null) return false; var alignment = (string)xf.Element(S.alignment).Attribute(SSNoNamespace.horizontal); var match = alignment == cell.HorizontalCellAlignment.ToString().ToLower(); @@ -625,11 +657,9 @@ private static bool MatchAlignment(XDocument sXDoc, XElement xf, CellDfn cell) private static bool MatchFormat(XDocument sXDoc, XElement xf, CellDfn cell) { - if ((int?)xf.Attribute(SSNoNamespace.applyNumberFormat) != 1 && - cell.FormatCode == null) + if ((int?)xf.Attribute(SSNoNamespace.applyNumberFormat) != 1 && cell.FormatCode == null) return true; - if (xf.Attribute(SSNoNamespace.applyNumberFormat) == null && - cell.FormatCode != null) + if (xf.Attribute(SSNoNamespace.applyNumberFormat) == null && cell.FormatCode != null) return false; var numFmtId = (int)xf.Attribute(SSNoNamespace.numFmtId); int? nfi = null; @@ -640,15 +670,12 @@ private static bool MatchFormat(XDocument sXDoc, XElement xf, CellDfn cell) if (nfi == numFmtId) return true; } - var numFmts = sXDoc - .Root - .Element(S.numFmts); + var numFmts = sXDoc.Root.Element(S.numFmts); if (numFmts == null) return false; var numFmt = numFmts .Elements(S.numFmt) - .FirstOrDefault(numFmtElement => - (int)numFmtElement.Attribute(SSNoNamespace.numFmtId) == numFmtId); + .FirstOrDefault(numFmtElement => (int)numFmtElement.Attribute(SSNoNamespace.numFmtId) == numFmtId); if (numFmt == null) return false; var styleFormatCode = (string)numFmt.Attribute(SSNoNamespace.formatCode); @@ -656,7 +683,8 @@ private static bool MatchFormat(XDocument sXDoc, XElement xf, CellDfn cell) return match; } - private static readonly string _EmptyXlsx = @"UEsDBBQABgAIAAAAIQBi7p1oYQEAAJAEAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC + private static readonly string _EmptyXlsx = + @"UEsDBBQABgAIAAAAIQBi7p1oYQEAAJAEAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -790,22 +818,17 @@ private static bool MatchFormat(XDocument sXDoc, XElement xf, CellDfn cell) eG1sUEsBAi0AFAAGAAgAAAAhAJtkFtU+AQAAUQIAABEAAAAAAAAAAAAAAAAA9xUAAGRvY1Byb3Bz L2NvcmUueG1sUEsBAi0AFAAGAAgAAAAhAHREzCiJAQAAEQMAABAAAAAAAAAAAAAAAAAAbBgAAGRv Y1Byb3BzL2FwcC54bWxQSwUGAAAAAAoACgCAAgAAKxsAAAAA"; - } public class SpreadsheetWriterInternalException : Exception { public SpreadsheetWriterInternalException() - : base("Internal error - unexpected content in _EmptyXlsx.") - { - } + : base("Internal error - unexpected content in _EmptyXlsx.") { } } public class InvalidSheetNameException : Exception { public InvalidSheetNameException(string name) - : base($"The supplied name ({name}) is not a valid XLSX worksheet name.") - { - } + : base($"The supplied name ({name}) is not a valid XLSX worksheet name.") { } } } diff --git a/Clippit/Excel/WorksheetAccessor.cs b/Clippit/Excel/WorksheetAccessor.cs index e96f6e3d..b9ca49ed 100644 --- a/Clippit/Excel/WorksheetAccessor.cs +++ b/Clippit/Excel/WorksheetAccessor.cs @@ -111,10 +111,12 @@ public int GetColumn() { return column; } + public object GetValue() { return cellValue; } + public int GetStyleIndex() { return styleIndex; @@ -126,14 +128,24 @@ public XElement GetElements(int row) var newCell = cellValue switch { - int or double => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), - new XElement(S.v, cellValue.ToString())), - bool value => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), - new XAttribute(NoNamespace.t, "b"), new XElement(S.v, value ? "1" : "0")), - string => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), + int or double => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), + new XElement(S.v, cellValue.ToString()) + ), + bool value => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), + new XAttribute(NoNamespace.t, "b"), + new XElement(S.v, value ? "1" : "0") + ), + string => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "inlineStr"), - new XElement(S._is, new XElement(S.t, cellValue.ToString()))), - _ => null + new XElement(S._is, new XElement(S.t, cellValue.ToString())) + ), + _ => null, }; if (newCell == null) throw new ArgumentException("Invalid cell type."); @@ -148,16 +160,23 @@ public XElement GetElements(int row) public class WorksheetAccessor { private static readonly XNamespace ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; - private static readonly XNamespace relationshipsns = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; + private static readonly XNamespace relationshipsns = + "http://schemas.openxmlformats.org/officeDocument/2006/relationships"; // Finds the WorksheetPart by sheet name public static WorksheetPart GetWorksheet(SpreadsheetDocument document, string worksheetName) { var workbook = document.WorkbookPart.GetXDocument(); - return (WorksheetPart)document.WorkbookPart.GetPartById( - workbook.Root.Element(S.sheets).Elements(S.sheet).Where( - s => s.Attribute(NoNamespace.name).Value.ToLower().Equals(worksheetName.ToLower())) - .FirstOrDefault().Attribute(R.id).Value); + return (WorksheetPart) + document.WorkbookPart.GetPartById( + workbook + .Root.Element(S.sheets) + .Elements(S.sheet) + .Where(s => s.Attribute(NoNamespace.name).Value.ToLower().Equals(worksheetName.ToLower())) + .FirstOrDefault() + .Attribute(R.id) + .Value + ); } // Creates a new worksheet with the specified name @@ -165,31 +184,50 @@ public static WorksheetPart AddWorksheet(SpreadsheetDocument document, string wo { // Create the empty sheet var worksheetPart = document.WorkbookPart.AddNewPart(); - worksheetPart.PutXDocument(new XDocument( - new XElement(S.worksheet, new XAttribute("xmlns", S.s), new XAttribute(XNamespace.Xmlns + "r", R.r), - new XElement(S.sheetData)))); + worksheetPart.PutXDocument( + new XDocument( + new XElement( + S.worksheet, + new XAttribute("xmlns", S.s), + new XAttribute(XNamespace.Xmlns + "r", R.r), + new XElement(S.sheetData) + ) + ) + ); var wb = document.WorkbookPart.GetXDocument(); // Generate a unique sheet ID number var sheetId = 1; if (wb.Root.Element(S.sheets).Elements(S.sheet).Count() != 0) - sheetId = wb.Root.Element(S.sheets).Elements(S.sheet).Max(n => Convert.ToInt32(n.Attribute(NoNamespace.sheetId).Value)) + 1; + sheetId = + wb.Root.Element(S.sheets) + .Elements(S.sheet) + .Max(n => Convert.ToInt32(n.Attribute(NoNamespace.sheetId).Value)) + 1; // If name is null, generate a name based on the sheet ID if (worksheetName == null) worksheetName = "Sheet" + sheetId; // Create the new sheet element in the workbook - wb.Root.Element(S.sheets).Add(new XElement(S.sheet, - new XAttribute(NoNamespace.name, worksheetName), - new XAttribute(NoNamespace.sheetId, sheetId), - new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(worksheetPart)))); + wb.Root.Element(S.sheets) + .Add( + new XElement( + S.sheet, + new XAttribute(NoNamespace.name, worksheetName), + new XAttribute(NoNamespace.sheetId, sheetId), + new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(worksheetPart)) + ) + ); document.WorkbookPart.PutXDocument(); return worksheetPart; } // Creates a new worksheet with the specified name and contents from a memory spreadsheet - public static void SetSheetContents(SpreadsheetDocument document, WorksheetPart worksheet, MemorySpreadsheet contents) + public static void SetSheetContents( + SpreadsheetDocument document, + WorksheetPart worksheet, + MemorySpreadsheet contents + ) { var worksheetXDocument = worksheet.GetXDocument(); worksheetXDocument.Root.Element(S.sheetData).ReplaceWith(contents.GetElements()); @@ -248,32 +286,52 @@ private static string GetSharedString(SpreadsheetDocument document, int index) private static XElement GetCell(XDocument worksheet, int column, int row) { var cellReference = GetColumnId(column) + row; - var rowElement = worksheet.Root - .Element(S.sheetData) - .Elements(S.row) - .Where(r => r.Attribute(NoNamespace.r).Value.Equals(row.ToString())).FirstOrDefault(); + var rowElement = worksheet + .Root.Element(S.sheetData) + .Elements(S.row) + .Where(r => r.Attribute(NoNamespace.r).Value.Equals(row.ToString())) + .FirstOrDefault(); if (rowElement == null) return null; - return rowElement.Elements(S.c).Where(c => c.Attribute(NoNamespace.r).Value.Equals(cellReference)).FirstOrDefault(); + return rowElement + .Elements(S.c) + .Where(c => c.Attribute(NoNamespace.r).Value.Equals(cellReference)) + .FirstOrDefault(); } // Sets the value for the specified cell // The "value" must be double/Double, int/Int32, bool/Boolean or string/String type - public static void SetCellValue(SpreadsheetDocument document, WorksheetPart worksheet, int row, int column, object value) + public static void SetCellValue( + SpreadsheetDocument document, + WorksheetPart worksheet, + int row, + int column, + object value + ) { var worksheetXDocument = worksheet.GetXDocument(); var cellReference = GetColumnId(column) + row; var newCell = value switch { - int or double => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), - new XElement(S.v, value.ToString())), - bool b => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), - new XAttribute(NoNamespace.t, "b"), new XElement(S.v, b ? "1" : "0")), - string => new XElement(S.c, new XAttribute(NoNamespace.r, cellReference), + int or double => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), + new XElement(S.v, value.ToString()) + ), + bool b => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), + new XAttribute(NoNamespace.t, "b"), + new XElement(S.v, b ? "1" : "0") + ), + string => new XElement( + S.c, + new XAttribute(NoNamespace.r, cellReference), new XAttribute(NoNamespace.t, "inlineStr"), - new XElement(S._is, new XElement(S.t, value.ToString()))), - _ => null + new XElement(S._is, new XElement(S.t, value.ToString())) + ), + _ => null, }; if (newCell == null) throw new ArgumentException("Invalid cell type."); @@ -288,8 +346,8 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) GetRowColumn(cellReference, out var row, out var column); // Find the row containing the cell to add the value to - var rowElement = worksheetXDocument.Root - .Element(S.sheetData) + var rowElement = worksheetXDocument + .Root.Element(S.sheetData) .Elements(S.row) .Where(t => t.Attribute(NoNamespace.r).Value == row.ToString()) .FirstOrDefault(); @@ -302,7 +360,7 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) //row elements must appear in order inside sheetData element if (worksheetXDocument.Root.Element(S.sheetData).HasElements) - { //if there are more rows already defined at sheetData element + { //if there are more rows already defined at sheetData element //find the row with the inmediate higher index for the row containing the cell to set the value to var rowAfterElement = FindRowAfter(worksheetXDocument, row); //if there is a row with an inmediate higher index already defined at sheetData @@ -312,12 +370,12 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) rowAfterElement.AddBeforeSelf(rowElement); } else - { //this row is going to be the one with the highest index (add it as the last element for sheetData) + { //this row is going to be the one with the highest index (add it as the last element for sheetData) worksheetXDocument.Root.Element(S.sheetData).Elements(S.row).Last().AddAfterSelf(rowElement); } } else - { //there are no other rows already defined at sheetData + { //there are no other rows already defined at sheetData //Add a new row elemento to sheetData worksheetXDocument.Root.Element(S.sheetData).Add(rowElement); } @@ -335,7 +393,7 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) .FirstOrDefault(); if (currentCell == null) - { //cell element does not exist at row indicated as parameter + { //cell element does not exist at row indicated as parameter //find the inmediate right column for the cell to set the value to var columnAfterXElement = FindColumAfter(worksheetXDocument, row, column); if (columnAfterXElement != null) @@ -344,7 +402,7 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) columnAfterXElement.AddBeforeSelf(newCell); } else - { //There is no inmediate right cell + { //There is no inmediate right cell //Add the new cell as the last element for the row rowElement.Add(newCell); } @@ -361,8 +419,8 @@ private static void SetCell(XDocument worksheetXDocument, XElement newCell) // Finds the row element (r) with a higher number than the specified "row" number private static XElement FindRowAfter(XDocument worksheet, int row) { - return worksheet.Root - .Element(S.sheetData) + return worksheet + .Root.Element(S.sheetData) .Elements(S.row) .FirstOrDefault(r => Convert.ToInt32(r.Attribute(NoNamespace.r).Value) > row); } @@ -370,12 +428,14 @@ private static XElement FindRowAfter(XDocument worksheet, int row) // Finds the cell element (c) in the specified row that is after the specified "column" number private static XElement FindColumAfter(XDocument worksheet, int row, int column) { - return worksheet.Root - .Element(S.sheetData) + return worksheet + .Root.Element(S.sheetData) .Elements(S.row) .FirstOrDefault(r => Convert.ToInt32(r.Attribute(NoNamespace.r).Value) == row) .Elements(S.c) - .FirstOrDefault(c => GetColumnNumber(c.Attribute(NoNamespace.r).Value) > GetColumnNumber(GetColumnId(column) + row)); + .FirstOrDefault(c => + GetColumnNumber(c.Attribute(NoNamespace.r).Value) > GetColumnNumber(GetColumnId(column) + row) + ); } // Converts the column reference string to a column number (e.g. A -> 1, B -> 2) @@ -406,17 +466,27 @@ private static void GetRowColumn(string cellReference, out int row, out int colu } // Returns the row and column numbers and worksheet part for the named range - public static WorksheetPart GetRange(SpreadsheetDocument doc, string rangeName, out int startRow, out int startColumn, out int endRow, out int endColumn) + public static WorksheetPart GetRange( + SpreadsheetDocument doc, + string rangeName, + out int startRow, + out int startColumn, + out int endRow, + out int endColumn + ) { var book = doc.WorkbookPart.GetXDocument(); if (book.Root.Element(S.definedNames) == null) throw new ArgumentException("Range name not found: " + rangeName); - var element = book.Root.Element(S.definedNames).Elements(S.definedName) - .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault(); + var element = book + .Root.Element(S.definedNames) + .Elements(S.definedName) + .Where(t => t.Attribute(NoNamespace.name).Value == rangeName) + .FirstOrDefault(); if (element == null) throw new ArgumentException("Range name not found: " + rangeName); var sheetName = element.Value.Substring(0, element.Value.IndexOf('!')); - var range = element.Value.Substring(element.Value.IndexOf('!') + 1).Replace("$",""); + var range = element.Value.Substring(element.Value.IndexOf('!') + 1).Replace("$", ""); var colonIndex = range.IndexOf(':'); GetRowColumn(range.Substring(0, colonIndex), out startRow, out startColumn); GetRowColumn(range.Substring(colonIndex + 1), out endRow, out endColumn); @@ -424,13 +494,24 @@ public static WorksheetPart GetRange(SpreadsheetDocument doc, string rangeName, } // Sets the named range with the specified range of row and column numbers - public static void SetRange(SpreadsheetDocument doc, string rangeName, string sheetName, int startRow, int startColumn, int endRow, int endColumn) + public static void SetRange( + SpreadsheetDocument doc, + string rangeName, + string sheetName, + int startRow, + int startColumn, + int endRow, + int endColumn + ) { var book = doc.WorkbookPart.GetXDocument(); if (book.Root.Element(S.definedNames) == null) book.Root.Add(new XElement(S.definedNames)); - var element = book.Root.Element(S.definedNames).Elements(S.definedName) - .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault(); + var element = book + .Root.Element(S.definedNames) + .Elements(S.definedName) + .Where(t => t.Attribute(NoNamespace.name).Value == rangeName) + .FirstOrDefault(); if (element == null) { element = new XElement(S.definedName, new XAttribute(NoNamespace.name, rangeName)); @@ -445,8 +526,11 @@ public static void UpdateRangeEndRow(SpreadsheetDocument doc, string rangeName, { // Update named range used by pivot table var book = doc.WorkbookPart.GetXDocument(); - var element = book.Root.Element(S.definedNames).Elements(S.definedName) - .Where(t => t.Attribute(NoNamespace.name).Value == rangeName).FirstOrDefault(); + var element = book + .Root.Element(S.definedNames) + .Elements(S.definedName) + .Where(t => t.Attribute(NoNamespace.name).Value == rangeName) + .FirstOrDefault(); if (element != null) { var original = element.Value; @@ -498,43 +582,68 @@ public static void FormulaReplaceSheetName(SpreadsheetDocument document, string } // Copy all cells in the specified range to a new location - public static void CopyCellRange(SpreadsheetDocument document, WorksheetPart worksheet, int startRow, int startColumn, int endRow, int endColumn, - int toRow, int toColumn) + public static void CopyCellRange( + SpreadsheetDocument document, + WorksheetPart worksheet, + int startRow, + int startColumn, + int endRow, + int endColumn, + int toRow, + int toColumn + ) { var rowOffset = toRow - startRow; var columnOffset = toColumn - startColumn; var worksheetXDocument = worksheet.GetXDocument(); for (var row = startRow; row <= endRow; row++) - for (var column = startColumn; column <= endColumn; column++) + for (var column = startColumn; column <= endColumn; column++) + { + var oldCell = GetCell(worksheetXDocument, column, row); + if (oldCell != null) { - var oldCell = GetCell(worksheetXDocument, column, row); - if (oldCell != null) + var newCell = new XElement(oldCell); + newCell.SetAttributeValue(NoNamespace.r, GetColumnId(column + columnOffset) + (row + rowOffset)); + var formula = newCell.Element(S.f); + if (formula != null) { - var newCell = new XElement(oldCell); - newCell.SetAttributeValue(NoNamespace.r, GetColumnId(column + columnOffset) + (row + rowOffset)); - var formula = newCell.Element(S.f); - if (formula != null) - { - var parser = new ParseFormula(formula.Value); - formula.SetValue(parser.ReplaceRelativeCell(rowOffset, columnOffset)); - } - SetCell(worksheetXDocument, newCell); + var parser = new ParseFormula(formula.Value); + formula.SetValue(parser.ReplaceRelativeCell(rowOffset, columnOffset)); } + SetCell(worksheetXDocument, newCell); } + } worksheet.PutXDocument(); ForceCalculateOnLoad(document); } // Creates a pivot table in the specified sheet using the specified range name // The new pivot table will not be configured with any fields in the rows, columns, filters or values - public static PivotTablePart CreatePivotTable(SpreadsheetDocument document, string rangeName, WorksheetPart sheet) + public static PivotTablePart CreatePivotTable( + SpreadsheetDocument document, + string rangeName, + WorksheetPart sheet + ) { - var sourceSheet = GetRange(document, rangeName, out var startRow, out var startColumn, out var endRow, out var endColumn); + var sourceSheet = GetRange( + document, + rangeName, + out var startRow, + out var startColumn, + out var endRow, + out var endColumn + ); // Fill out pivotFields element (for PivotTablePart) and cacheFields element (for PivotTableCacheDefinitionPart) // with an element for each column in the source range - var pivotFields = new XElement(S.pivotFields, new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString())); - var cacheFields = new XElement(S.cacheFields, new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString())); + var pivotFields = new XElement( + S.pivotFields, + new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString()) + ); + var cacheFields = new XElement( + S.cacheFields, + new XAttribute(NoNamespace.count, (endColumn - startColumn + 1).ToString()) + ); for (var column = startColumn; column <= endColumn; column++) { pivotFields.Add(new XElement(S.pivotField, new XAttribute(NoNamespace.showAll, "0"))); @@ -558,20 +667,37 @@ public static PivotTablePart CreatePivotTable(SpreadsheetDocument document, stri if (Convert.ToDouble(value) > maxValue) maxValue = Convert.ToDouble(value); } - sharedItems.Add(new XAttribute(NoNamespace.containsSemiMixedTypes, "0"), - new XAttribute(NoNamespace.containsString, "0"), new XAttribute(NoNamespace.containsNumber, "1"), - new XAttribute(NoNamespace.minValue, minValue.ToString()), new XAttribute(NoNamespace.maxValue, maxValue.ToString())); + sharedItems.Add( + new XAttribute(NoNamespace.containsSemiMixedTypes, "0"), + new XAttribute(NoNamespace.containsString, "0"), + new XAttribute(NoNamespace.containsNumber, "1"), + new XAttribute(NoNamespace.minValue, minValue.ToString()), + new XAttribute(NoNamespace.maxValue, maxValue.ToString()) + ); if (!hasDouble) sharedItems.Add(new XAttribute(NoNamespace.containsInteger, "1")); } - cacheFields.Add(new XElement(S.cacheField, new XAttribute(NoNamespace.name, GetCellValue(document, sourceSheet, column, startRow).ToString()), - new XAttribute(NoNamespace.numFmtId, "0"), sharedItems)); + cacheFields.Add( + new XElement( + S.cacheField, + new XAttribute( + NoNamespace.name, + GetCellValue(document, sourceSheet, column, startRow).ToString() + ), + new XAttribute(NoNamespace.numFmtId, "0"), + sharedItems + ) + ); } // Fill out pivotCacheRecords element (for PivotTableCacheRecordsPart) with an element // for each row in the source range - var pivotCacheRecords = new XElement(S.pivotCacheRecords, new XAttribute("xmlns", S.s), - new XAttribute(XNamespace.Xmlns + "r", R.r), new XAttribute(NoNamespace.count, (endRow - startRow).ToString())); + var pivotCacheRecords = new XElement( + S.pivotCacheRecords, + new XAttribute("xmlns", S.s), + new XAttribute(XNamespace.Xmlns + "r", R.r), + new XAttribute(NoNamespace.count, (endRow - startRow).ToString()) + ); for (var row = startRow + 1; row <= endRow; row++) { var r = new XElement(S.r); @@ -596,12 +722,23 @@ public static PivotTablePart CreatePivotTable(SpreadsheetDocument document, stri // Set content for the PivotTableCacheRecordsPart and PivotTableCacheDefinitionPart records.PutXDocument(new XDocument(pivotCacheRecords)); - cacheDef.PutXDocument(new XDocument(new XElement(S.pivotCacheDefinition, new XAttribute("xmlns", S.s), - new XAttribute(XNamespace.Xmlns + "r", R.r), new XAttribute(R.id, cacheDef.GetIdOfPart(records)), - new XAttribute(NoNamespace.recordCount, (endRow - startRow).ToString()), - new XElement(S.cacheSource, new XAttribute(NoNamespace.type, "worksheet"), - new XElement(S.worksheetSource, new XAttribute(NoNamespace.name, rangeName))), - cacheFields))); + cacheDef.PutXDocument( + new XDocument( + new XElement( + S.pivotCacheDefinition, + new XAttribute("xmlns", S.s), + new XAttribute(XNamespace.Xmlns + "r", R.r), + new XAttribute(R.id, cacheDef.GetIdOfPart(records)), + new XAttribute(NoNamespace.recordCount, (endRow - startRow).ToString()), + new XElement( + S.cacheSource, + new XAttribute(NoNamespace.type, "worksheet"), + new XElement(S.worksheetSource, new XAttribute(NoNamespace.name, rangeName)) + ), + cacheFields + ) + ) + ); // Create the pivotCache entry in the workbook part var cacheId = 1; @@ -611,34 +748,68 @@ public static PivotTablePart CreatePivotTable(SpreadsheetDocument document, stri else { if (wb.Root.Element(S.pivotCaches).Elements(S.pivotCache).Count() != 0) - cacheId = wb.Root.Element(S.pivotCaches).Elements(S.pivotCache).Max(n => Convert.ToInt32(n.Attribute(NoNamespace.cacheId).Value)) + 1; + cacheId = + wb.Root.Element(S.pivotCaches) + .Elements(S.pivotCache) + .Max(n => Convert.ToInt32(n.Attribute(NoNamespace.cacheId).Value)) + 1; } - wb.Root.Element(S.pivotCaches).Add(new XElement(S.pivotCache, - new XAttribute(NoNamespace.cacheId, cacheId), - new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(cacheDef)))); + wb.Root.Element(S.pivotCaches) + .Add( + new XElement( + S.pivotCache, + new XAttribute(NoNamespace.cacheId, cacheId), + new XAttribute(R.id, document.WorkbookPart.GetIdOfPart(cacheDef)) + ) + ); document.WorkbookPart.PutXDocument(); // Set the content for the PivotTablePart - pivotTable.PutXDocument(new XDocument(new XElement(S.pivotTableDefinition, new XAttribute("xmlns", S.s), - new XAttribute(NoNamespace.name, "PivotTable1"), new XAttribute(NoNamespace.cacheId, cacheId.ToString()), - new XAttribute(NoNamespace.dataCaption, "Values"), - new XElement(S.location, new XAttribute(NoNamespace._ref, "A3:C20"), - new XAttribute(NoNamespace.firstHeaderRow, "1"), new XAttribute(NoNamespace.firstDataRow, "1"), - new XAttribute(NoNamespace.firstDataCol, "0")), pivotFields))); + pivotTable.PutXDocument( + new XDocument( + new XElement( + S.pivotTableDefinition, + new XAttribute("xmlns", S.s), + new XAttribute(NoNamespace.name, "PivotTable1"), + new XAttribute(NoNamespace.cacheId, cacheId.ToString()), + new XAttribute(NoNamespace.dataCaption, "Values"), + new XElement( + S.location, + new XAttribute(NoNamespace._ref, "A3:C20"), + new XAttribute(NoNamespace.firstHeaderRow, "1"), + new XAttribute(NoNamespace.firstDataRow, "1"), + new XAttribute(NoNamespace.firstDataCol, "0") + ), + pivotFields + ) + ) + ); return pivotTable; } - public enum PivotAxis { Row, Column, Page }; - public static void AddPivotAxis(SpreadsheetDocument document, WorksheetPart sheet, string fieldName, PivotAxis axis) + public enum PivotAxis + { + Row, + Column, + Page, + }; + + public static void AddPivotAxis( + SpreadsheetDocument document, + WorksheetPart sheet, + string fieldName, + PivotAxis axis + ) { // Create indexed items in cache and definition var pivotTablePart = sheet.GetPartsOfType().First(); var cacheDefPart = pivotTablePart.GetPartsOfType().First(); var recordsPart = cacheDefPart.GetPartsOfType().First(); var cacheDef = cacheDefPart.GetXDocument(); - var index = Array.FindIndex(cacheDef.Descendants(S.cacheField).ToArray(), - z => z.Attribute(NoNamespace.name).Value == fieldName); + var index = Array.FindIndex( + cacheDef.Descendants(S.cacheField).ToArray(), + z => z.Attribute(NoNamespace.name).Value == fieldName + ); var records = recordsPart.GetXDocument(); var values = new List(); foreach (var rec in records.Descendants(S.r)) @@ -660,15 +831,28 @@ public static void AddPivotAxis(SpreadsheetDocument document, WorksheetPart shee // Add axis definition to pivot table field var pivotTable = pivotTablePart.GetXDocument(); var pivotField = pivotTable.Descendants(S.pivotField).Skip(index).First(); - var items = new XElement(S.items, new XAttribute(NoNamespace.count, values.Count + 1), - values.OrderBy(z => z.Attribute(NoNamespace.v).Value).Select(z => new XElement(S.item, - new XAttribute(NoNamespace.x, Array.FindIndex(values.ToArray(), - a => a.Attribute(NoNamespace.v).Value == z.Attribute(NoNamespace.v).Value))))); + var items = new XElement( + S.items, + new XAttribute(NoNamespace.count, values.Count + 1), + values + .OrderBy(z => z.Attribute(NoNamespace.v).Value) + .Select(z => new XElement( + S.item, + new XAttribute( + NoNamespace.x, + Array.FindIndex( + values.ToArray(), + a => a.Attribute(NoNamespace.v).Value == z.Attribute(NoNamespace.v).Value + ) + ) + )) + ); items.Add(new XElement(S.item, new XAttribute(NoNamespace.t, "default"))); switch (axis) { case PivotAxis.Column: pivotField.Add(new XAttribute(NoNamespace.axis, "axisCol"), items); + // Add to colFields { var fields = pivotTable.Element(S.pivotTableDefinition).Element(S.colFields); @@ -687,6 +871,7 @@ public static void AddPivotAxis(SpreadsheetDocument document, WorksheetPart shee break; case PivotAxis.Row: pivotField.Add(new XAttribute(NoNamespace.axis, "axisRow"), items); + // Add to rowFields { var fields = pivotTable.Element(S.pivotTableDefinition).Element(S.rowFields); @@ -701,6 +886,7 @@ public static void AddPivotAxis(SpreadsheetDocument document, WorksheetPart shee break; case PivotAxis.Page: pivotField.Add(new XAttribute(NoNamespace.axis, "axisPage"), items); + // Add to pageFields { var fields = pivotTable.Element(S.pivotTableDefinition).Element(S.pageFields); @@ -790,8 +976,10 @@ public static void AddDataValue(SpreadsheetDocument document, WorksheetPart shee var pivotTablePart = sheet.GetPartsOfType().First(); var cacheDefPart = pivotTablePart.GetPartsOfType().First(); var cacheDef = cacheDefPart.GetXDocument(); - var index = Array.FindIndex(cacheDef.Descendants(S.cacheField).ToArray(), - z => z.Attribute(NoNamespace.name).Value == fieldName); + var index = Array.FindIndex( + cacheDef.Descendants(S.cacheField).ToArray(), + z => z.Attribute(NoNamespace.name).Value == fieldName + ); var pivotTable = pivotTablePart.GetXDocument(); var pivotField = pivotTable.Descendants(S.pivotField).Skip(index).First(); pivotField.Add(new XAttribute(NoNamespace.dataField, "1")); @@ -808,13 +996,19 @@ public static void AddDataValue(SpreadsheetDocument document, WorksheetPart shee prev = pivotTable.Element(S.pivotTableDefinition).Element(S.pivotFields); prev.AddAfterSelf(fields); } - fields.Add(new XElement(S.dataField, new XAttribute(NoNamespace.name, "Sum of " + fieldName), - new XAttribute(NoNamespace.fld, index), new XAttribute(NoNamespace.baseField, 0), - new XAttribute(NoNamespace.baseItem, 0))); + fields.Add( + new XElement( + S.dataField, + new XAttribute(NoNamespace.name, "Sum of " + fieldName), + new XAttribute(NoNamespace.fld, index), + new XAttribute(NoNamespace.baseField, 0), + new XAttribute(NoNamespace.baseItem, 0) + ) + ); var count = fields.Elements(S.dataField).Count(); fields.Attribute(NoNamespace.count).Value = count.ToString(); if (count == 2) - { // Only when data field count goes from 1 to 2 do we add a special column to label the data fields + { // Only when data field count goes from 1 to 2 do we add a special column to label the data fields AddDataValueLabel(document, sheet, PivotAxis.Column); } pivotTablePart.PutXDocument(); @@ -834,17 +1028,21 @@ private static void ForcePivotRefresh(PivotTableCacheDefinitionPart cacheDef) public static void CheckNumberFormat(SpreadsheetDocument document, int fmtID, string formatCode) { - var numFmt = new XElement(S.numFmt, new XAttribute(NoNamespace.numFmtId, fmtID.ToString()), - new XAttribute(NoNamespace.formatCode, formatCode)); + var numFmt = new XElement( + S.numFmt, + new XAttribute(NoNamespace.numFmtId, fmtID.ToString()), + new XAttribute(NoNamespace.formatCode, formatCode) + ); var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); var numFmts = styles.Root.Element(S.numFmts); if (numFmts == null) { - styles.Root.Element(S.fonts).AddBeforeSelf(new XElement(S.numFmts, new XAttribute(NoNamespace.count, "0"))); + styles + .Root.Element(S.fonts) + .AddBeforeSelf(new XElement(S.numFmts, new XAttribute(NoNamespace.count, "0"))); numFmts = styles.Root.Element(S.numFmts); } - var index = Array.FindIndex(numFmts.Elements(S.numFmt).ToArray(), - z => XNode.DeepEquals(z, numFmt)); + var index = Array.FindIndex(numFmts.Elements(S.numFmt).ToArray(), z => XNode.DeepEquals(z, numFmt)); if (index == -1) { numFmts.Add(numFmt); @@ -855,7 +1053,11 @@ public static void CheckNumberFormat(SpreadsheetDocument document, int fmtID, st public class ColorInfo { - public enum ColorType { Theme, Indexed }; + public enum ColorType + { + Theme, + Indexed, + }; private readonly bool Auto; private readonly string RGB; @@ -867,6 +1069,7 @@ public ColorInfo() { Auto = true; } + public ColorInfo(ColorType type, int value) { if (type == ColorType.Indexed) @@ -874,11 +1077,13 @@ public ColorInfo(ColorType type, int value) else if (type == ColorType.Theme) Theme = value; } + public ColorInfo(int theme, double tint) { Theme = theme; Tint = tint; } + public ColorInfo(string rgb) { RGB = rgb; @@ -903,7 +1108,12 @@ public XElement GetXElement(XName colorName) public class Font { - public enum SchemeType { None, Major, Minor }; + public enum SchemeType + { + None, + Major, + Minor, + }; public bool Bold { get; set; } public ColorInfo Color { get; set; } @@ -964,8 +1174,7 @@ public static int GetFontIndex(SpreadsheetDocument document, Font f) var font = f.GetXElement(); var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); var fonts = styles.Root.Element(S.fonts); - var index = Array.FindIndex(fonts.Elements(S.font).ToArray(), - z => XNode.DeepEquals(z, font)); + var index = Array.FindIndex(fonts.Elements(S.font).ToArray(), z => XNode.DeepEquals(z, font)); if (index != -1) return index; fonts.Add(font); @@ -978,8 +1187,25 @@ public class PatternFill { public enum PatternType { - None, Solid, DarkDown, DarkGray, DarkGrid, DarkHorizontal, DarkTrellis, DarkUp, DarkVertical, - Gray0625, Gray125, LightDown, LightGray, LightGrid, LightHorizontal, LightTrellis, LightUp, LightVertical, MediumGray + None, + Solid, + DarkDown, + DarkGray, + DarkGrid, + DarkHorizontal, + DarkTrellis, + DarkUp, + DarkVertical, + Gray0625, + Gray125, + LightDown, + LightGray, + LightGrid, + LightHorizontal, + LightTrellis, + LightUp, + LightVertical, + MediumGray, }; private readonly PatternType Pattern; @@ -1118,9 +1344,13 @@ public XElement GetXElement() var gradient = new XElement(S.gradientFill); if (PathGradient) { - gradient.Add(new XAttribute(NoNamespace.type, "path"), - new XAttribute(NoNamespace.left, PathLeft.ToString()), new XAttribute(NoNamespace.right, PathRight.ToString()), - new XAttribute(NoNamespace.top, PathTop.ToString()), new XAttribute(NoNamespace.bottom, PathBottom.ToString())); + gradient.Add( + new XAttribute(NoNamespace.type, "path"), + new XAttribute(NoNamespace.left, PathLeft.ToString()), + new XAttribute(NoNamespace.right, PathRight.ToString()), + new XAttribute(NoNamespace.top, PathTop.ToString()), + new XAttribute(NoNamespace.bottom, PathBottom.ToString()) + ); } else { @@ -1146,8 +1376,7 @@ private static int GetFillIndex(SpreadsheetDocument document, XElement fill) { var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); var fills = styles.Root.Element(S.fills); - var index = Array.FindIndex(fills.Elements(S.fill).ToArray(), - z => XNode.DeepEquals(z, fill)); + var index = Array.FindIndex(fills.Elements(S.fill).ToArray(), z => XNode.DeepEquals(z, fill)); if (index != -1) return index; fills.Add(fill); @@ -1160,9 +1389,22 @@ public class BorderLine { public enum LineStyle { - None, DashDot, DashDotDot, Dashed, Dotted, Double, Hair, - Medium, MediumDashDot, MediumDashDotDot, MediumDashed, SlantDashDot, Thick, Thin + None, + DashDot, + DashDotDot, + Dashed, + Dotted, + Double, + Hair, + Medium, + MediumDashDot, + MediumDashDotDot, + MediumDashed, + SlantDashDot, + Thick, + Thin, }; + private readonly LineStyle Style; private readonly ColorInfo Color; @@ -1277,8 +1519,7 @@ public static int GetBorderIndex(SpreadsheetDocument document, Border b) var border = b.GetXElement(); var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); var borders = styles.Root.Element(S.borders); - var index = Array.FindIndex(borders.Elements(S.border).ToArray(), - z => XNode.DeepEquals(z, border)); + var index = Array.FindIndex(borders.Elements(S.border).ToArray(), z => XNode.DeepEquals(z, border)); if (index != -1) return index; borders.Add(border); @@ -1290,22 +1531,33 @@ public static int GetBorderIndex(SpreadsheetDocument document, Border b) public static int GetStyleIndex(SpreadsheetDocument document, string styleName) { var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); - var xfId = styles.Root.Element(S.cellStyles).Elements(S.cellStyle) + var xfId = styles + .Root.Element(S.cellStyles) + .Elements(S.cellStyle) .Where(t => t.Attribute(NoNamespace.name).Value == styleName) - .FirstOrDefault().Attribute(NoNamespace.xfId).Value; + .FirstOrDefault() + .Attribute(NoNamespace.xfId) + .Value; var cellXfs = styles.Root.Element(S.cellXfs); - var index = Array.FindIndex(cellXfs.Elements(S.xf).ToArray(), - z => z.Attribute(NoNamespace.xfId).Value == xfId); + var index = Array.FindIndex( + cellXfs.Elements(S.xf).ToArray(), + z => z.Attribute(NoNamespace.xfId).Value == xfId + ); if (index != -1) return index; var cellStyleXf = styles.Root.Element(S.cellStyleXfs).Elements(S.xf).ToArray()[Convert.ToInt32(xfId)]; if (cellStyleXf != null) - { // Create new xf element under cellXfs - cellXfs.Add(new XElement(S.xf, new XAttribute(NoNamespace.numFmtId, cellStyleXf.Attribute(NoNamespace.numFmtId).Value), - new XAttribute(NoNamespace.fontId, cellStyleXf.Attribute(NoNamespace.fontId).Value), - new XAttribute(NoNamespace.fillId, cellStyleXf.Attribute(NoNamespace.fillId).Value), - new XAttribute(NoNamespace.borderId, cellStyleXf.Attribute(NoNamespace.borderId).Value), - new XAttribute(NoNamespace.xfId, xfId))); + { // Create new xf element under cellXfs + cellXfs.Add( + new XElement( + S.xf, + new XAttribute(NoNamespace.numFmtId, cellStyleXf.Attribute(NoNamespace.numFmtId).Value), + new XAttribute(NoNamespace.fontId, cellStyleXf.Attribute(NoNamespace.fontId).Value), + new XAttribute(NoNamespace.fillId, cellStyleXf.Attribute(NoNamespace.fillId).Value), + new XAttribute(NoNamespace.borderId, cellStyleXf.Attribute(NoNamespace.borderId).Value), + new XAttribute(NoNamespace.xfId, xfId) + ) + ); cellXfs.Attribute(NoNamespace.count).Value = cellXfs.Elements(S.xf).Count().ToString(); document.WorkbookPart.WorkbookStylesPart.PutXDocument(); return cellXfs.Elements(S.xf).Count() - 1; @@ -1316,8 +1568,26 @@ public static int GetStyleIndex(SpreadsheetDocument document, string styleName) public class CellAlignment { - public enum Horizontal { General, Center, CenterContinuous, Distributed, Fill, Justify, Left, Right }; - public enum Vertical { Bottom, Center, Distributed, Justify, Top }; + public enum Horizontal + { + General, + Center, + CenterContinuous, + Distributed, + Fill, + Justify, + Left, + Right, + }; + + public enum Vertical + { + Bottom, + Center, + Distributed, + Justify, + Top, + }; public Horizontal HorizontalAlignment { get; set; } public int Indent { get; set; } @@ -1398,15 +1668,29 @@ public XElement GetXElement() } } - public static int GetStyleIndex(SpreadsheetDocument document, int numFmt, int font, int fill, int border, CellAlignment alignment, bool hidden, bool locked) + public static int GetStyleIndex( + SpreadsheetDocument document, + int numFmt, + int font, + int fill, + int border, + CellAlignment alignment, + bool hidden, + bool locked + ) { - var xf = new XElement(S.xf, new XAttribute(NoNamespace.numFmtId, numFmt), - new XAttribute(NoNamespace.fontId, font), new XAttribute(NoNamespace.fillId, fill), - new XAttribute(NoNamespace.borderId, border), new XAttribute(NoNamespace.xfId, 0), + var xf = new XElement( + S.xf, + new XAttribute(NoNamespace.numFmtId, numFmt), + new XAttribute(NoNamespace.fontId, font), + new XAttribute(NoNamespace.fillId, fill), + new XAttribute(NoNamespace.borderId, border), + new XAttribute(NoNamespace.xfId, 0), new XAttribute(NoNamespace.applyNumberFormat, (numFmt == 0) ? 0 : 1), new XAttribute(NoNamespace.applyFont, (font == 0) ? 0 : 1), new XAttribute(NoNamespace.applyFill, (fill == 0) ? 0 : 1), - new XAttribute(NoNamespace.applyBorder, (border == 0) ? 0 : 1)); + new XAttribute(NoNamespace.applyBorder, (border == 0) ? 0 : 1) + ); if (alignment != null) { xf.Add(new XAttribute(NoNamespace.applyAlignment, "1")); @@ -1429,8 +1713,7 @@ public static int GetStyleIndex(SpreadsheetDocument document, int numFmt, int fo var styles = document.WorkbookPart.WorkbookStylesPart.GetXDocument(); var cellXfs = styles.Root.Element(S.cellXfs); - var index = Array.FindIndex(cellXfs.Elements(S.xf).ToArray(), - z => XNode.DeepEquals(z, xf)); + var index = Array.FindIndex(cellXfs.Elements(S.xf).ToArray(), z => XNode.DeepEquals(z, xf)); if (index != -1) return index; cellXfs.Add(xf); @@ -1443,8 +1726,10 @@ public static void CreateDefaultStyles(SpreadsheetDocument document) { // Create the style part var stylesPart = document.WorkbookPart.AddNewPart(); - stylesPart.PutXDocument(new XDocument(XElement.Parse( -@" + stylesPart.PutXDocument( + new XDocument( + XElement.Parse( + @" @@ -1973,7 +2258,10 @@ public static void CreateDefaultStyles(SpreadsheetDocument document) -"))); +" + ) + ) + ); } /// @@ -1983,10 +2271,15 @@ public static void CreateDefaultStyles(SpreadsheetDocument document) /// Values for worksheet content /// Header row /// - internal static WorksheetPart Create(SpreadsheetDocument document, List headerList, string[][] valueTable, int headerRow) + internal static WorksheetPart Create( + SpreadsheetDocument document, + List headerList, + string[][] valueTable, + int headerRow + ) { var xDocument = CreateEmptyWorksheet(); - + for (var i = 0; i < headerList.Count; i++) { AddValue(xDocument, headerRow, i + 1, headerList[i]); @@ -2011,14 +2304,14 @@ internal static WorksheetPart Create(SpreadsheetDocument document, List /// Document with contents for an empty worksheet private static XDocument CreateEmptyWorksheet() { - var document = - new XDocument( - new XElement(ns + "worksheet", - new XAttribute("xmlns", ns), - new XAttribute(XNamespace.Xmlns + "r", relationshipsns), - new XElement(ns + "sheetData") - ) - ); + var document = new XDocument( + new XElement( + ns + "worksheet", + new XAttribute("xmlns", ns), + new XAttribute(XNamespace.Xmlns + "r", relationshipsns), + new XElement(ns + "sheetData") + ) + ); return document; } @@ -2037,30 +2330,22 @@ private static void AddValue(XDocument worksheet, int row, int column, string va var valueIsNumeric = double.TryParse(value, out var numericValue); //Creating the new cell element (markup) - var newCellXElement = valueIsNumeric ? - new XElement(ns + "c", - new XAttribute("r", cellReference), - new XElement(ns + "v", numericValue) - ) - : - new XElement(ns + "c", - new XAttribute("r", cellReference), - new XAttribute("t", "inlineStr"), - new XElement(ns + "is", - new XElement(ns + "t", value) - ) - ); + var newCellXElement = valueIsNumeric + ? new XElement(ns + "c", new XAttribute("r", cellReference), new XElement(ns + "v", numericValue)) + : new XElement( + ns + "c", + new XAttribute("r", cellReference), + new XAttribute("t", "inlineStr"), + new XElement(ns + "is", new XElement(ns + "t", value)) + ); // Find the row containing the cell to add the value to XName rowName = "r"; - var rowElement = - worksheet.Root - .Element(ns + "sheetData") - .Elements(ns + "row") - .Where( - t => t.Attribute(rowName).Value == row.ToString() - ) - .FirstOrDefault(); + var rowElement = worksheet + .Root.Element(ns + "sheetData") + .Elements(ns + "row") + .Where(t => t.Attribute(rowName).Value == row.ToString()) + .FirstOrDefault(); if (rowElement == null) { @@ -2069,9 +2354,8 @@ private static void AddValue(XDocument worksheet, int row, int column, string va rowElement = CreateEmptyRow(row); //row elements must appear in order inside sheetData element - if (worksheet.Root - .Element(ns + "sheetData").HasElements) - { //if there are more rows already defined at sheetData element + if (worksheet.Root.Element(ns + "sheetData").HasElements) + { //if there are more rows already defined at sheetData element //find the row with the inmediate higher index for the row containing the cell to set the value to var rowAfterElement = FindRowAfter(worksheet, row); //if there is a row with an inmediate higher index already defined at sheetData @@ -2081,16 +2365,15 @@ private static void AddValue(XDocument worksheet, int row, int column, string va rowAfterElement.AddBeforeSelf(rowElement); } else - { //this row is going to be the one with the highest index (add it as the last element for sheetData) + { //this row is going to be the one with the highest index (add it as the last element for sheetData) worksheet.Root.Element(ns + "sheetData").Elements(ns + "row").Last().AddAfterSelf(rowElement); } } else - { //there are no other rows already defined at sheetData + { //there are no other rows already defined at sheetData //Add a new row elemento to sheetData worksheet - .Root - .Element(ns + "sheetData") + .Root.Element(ns + "sheetData") .Add( rowElement //= CreateEmptyRow(row) ); @@ -2105,12 +2388,11 @@ private static void AddValue(XDocument worksheet, int row, int column, string va //look if cell already exist at that row var currentCellXElement = rowElement .Elements(ns + "c") - .Where( - t => t.Attribute("r").Value == cellReference - ).FirstOrDefault(); + .Where(t => t.Attribute("r").Value == cellReference) + .FirstOrDefault(); if (currentCellXElement == null) - { //cell element does not exist at row indicated as parameter + { //cell element does not exist at row indicated as parameter //find the inmediate right column for the cell to set the value to var columnAfterXElement = FindColumAfter(worksheet, row, column); if (columnAfterXElement != null) @@ -2119,7 +2401,7 @@ private static void AddValue(XDocument worksheet, int row, int column, string va columnAfterXElement.AddBeforeSelf(newCellXElement); } else - { //There is no inmediate right cell + { //There is no inmediate right cell //Add the new cell as the last element for the row rowElement.Add(newCellXElement); } @@ -2147,27 +2429,21 @@ public static WorksheetPart Add(SpreadsheetDocument doc, XDocument worksheet) // Associates the worksheet part to the workbook part var document = doc.WorkbookPart.GetXDocument(); - var sheetId = - document.Root - .Element(ns + "sheets") - .Elements(ns + "sheet") - .Count() + 1; + var sheetId = document.Root.Element(ns + "sheets").Elements(ns + "sheet").Count() + 1; var worksheetCount = - document.Root - .Element(ns + "sheets") - .Elements(ns + "sheet") - .Where( - t => - t.Attribute("name").Value.StartsWith("sheet", StringComparison.OrdinalIgnoreCase) - ) - .Count() + 1; + document + .Root.Element(ns + "sheets") + .Elements(ns + "sheet") + .Where(t => t.Attribute("name").Value.StartsWith("sheet", StringComparison.OrdinalIgnoreCase)) + .Count() + 1; // Adds content to workbook document to reference worksheet document - document.Root - .Element(ns + "sheets") + document + .Root.Element(ns + "sheets") .Add( - new XElement(ns + "sheet", + new XElement( + ns + "sheet", new XAttribute("name", $"sheet{worksheetCount}"), new XAttribute("sheetId", sheetId), new XAttribute(relationshipsns + "id", workbook.GetIdOfPart(worksheetPart)) diff --git a/Clippit/Excel/XlsxTables.cs b/Clippit/Excel/XlsxTables.cs index 4e905264..55862d0a 100644 --- a/Clippit/Excel/XlsxTables.cs +++ b/Clippit/Excel/XlsxTables.cs @@ -23,31 +23,37 @@ public class Table public int BottomRow { get; set; } public int? HeaderRowCount { get; set; } public int? TotalsRowCount { get; set; } - public string TableType { get; set; } // external data query, data in worksheet, or XML data + public string TableType { get; set; } // external data query, data in worksheet, or XML data public TableDefinitionPart TableDefinitionPart { get; set; } public WorksheetPart Parent { get; set; } - public Table(WorksheetPart parent) { Parent = parent; } + + public Table(WorksheetPart parent) + { + Parent = parent; + } + public IEnumerable TableColumns() { XNamespace x = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; return TableDefinitionPart .GetXDocument() - .Root - .Element(x + "tableColumns") + .Root.Element(x + "tableColumns") .Elements(x + "tableColumn") - .Select((c, i) => - new TableColumn(this) - { - Id = (int)c.Attribute("id"), - ColumnNumber = this.LeftColumn + i, - Name = (string)c.Attribute("name"), - DataDxfId = (int?)c.Attribute("dataDxfId"), - QueryTableFieldId = (int?)c.Attribute("queryTableFieldId"), - UniqueName = (string)c.Attribute("uniqueName"), - ColumnIndex = i, - } + .Select( + (c, i) => + new TableColumn(this) + { + Id = (int)c.Attribute("id"), + ColumnNumber = this.LeftColumn + i, + Name = (string)c.Attribute("name"), + DataDxfId = (int?)c.Attribute("dataDxfId"), + QueryTableFieldId = (int?)c.Attribute("queryTableFieldId"), + UniqueName = (string)c.Attribute("uniqueName"), + ColumnIndex = i, + } ); } + public IEnumerable TableRows() { var refStart = Ref.Split(':').First(); @@ -64,8 +70,7 @@ public IEnumerable TableRows() { var rowId = int.Parse(r.RowId); return rowId >= rowStart && rowId <= rowEnd; - } - ) + }) .Select(r => new TableRow(this) { Row = r }); } } @@ -80,27 +85,35 @@ public class TableColumn public int ColumnNumber { get; set; } public int ColumnIndex { get; set; } public Table Parent { get; set; } - public TableColumn(Table parent) { Parent = parent; } + + public TableColumn(Table parent) + { + Parent = parent; + } } public class TableRow { public Row Row { get; set; } public Table Parent { get; set; } - public TableRow(Table parent) { Parent = parent; } + + public TableRow(Table parent) + { + Parent = parent; + } + public TableCell this[string columnName] { get { - var tc = Parent - .TableColumns() - .Where(x => x.Name.ToLower() == columnName.ToLower()) - .FirstOrDefault(); + var tc = Parent.TableColumns().Where(x => x.Name.ToLower() == columnName.ToLower()).FirstOrDefault(); if (tc == null) throw new Exception("Invalid column name: " + columnName); var refs = Parent.Ref.Split(':'); var startRefs = XlsxTables.SplitAddress(refs[0]); - var columnAddress = XlsxTables.IndexToColumnAddress(XlsxTables.ColumnAddressToIndex(startRefs[0]) + tc.ColumnIndex); + var columnAddress = XlsxTables.IndexToColumnAddress( + XlsxTables.ColumnAddressToIndex(startRefs[0]) + tc.ColumnIndex + ); var cell = Row.Cells().Where(c => c.ColumnAddress == columnAddress).FirstOrDefault(); if (cell != null) { @@ -118,129 +131,176 @@ public TableCell this[string columnName] public class TableCell : IEquatable { public string Value { get; set; } + public TableCell(string v) { Value = v; } + public override string ToString() { return Value; } + public override bool Equals(object obj) { return this.Value == ((TableCell)obj).Value; } + bool IEquatable.Equals(TableCell other) { return this.Value == other.Value; } + public override int GetHashCode() { return this.Value.GetHashCode(); } + public static bool operator ==(TableCell left, TableCell right) { - if (left != (object)right) return false; + if (left != (object)right) + return false; return left.Value == right.Value; } + public static bool operator !=(TableCell left, TableCell right) { - if (left != (object)right) return false; + if (left != (object)right) + return false; return left.Value != right.Value; } + public static explicit operator string(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return cell.Value; } + public static explicit operator bool(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return cell.Value == "1"; } + public static explicit operator bool?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return cell.Value == "1"; } + public static explicit operator int(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return int.Parse(cell.Value); } + public static explicit operator int?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return int.Parse(cell.Value); } + public static explicit operator uint(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return uint.Parse(cell.Value); } + public static explicit operator uint?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return uint.Parse(cell.Value); } + public static explicit operator long(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return long.Parse(cell.Value); } + public static explicit operator long?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return long.Parse(cell.Value); } + public static explicit operator ulong(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return ulong.Parse(cell.Value); } + public static explicit operator ulong?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return ulong.Parse(cell.Value); } + public static explicit operator float(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return float.Parse(cell.Value); } + public static explicit operator float?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return float.Parse(cell.Value); } + public static explicit operator double(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return double.Parse(cell.Value); } + public static explicit operator double?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return double.Parse(cell.Value); } + public static explicit operator decimal(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return decimal.Parse(cell.Value); } + public static explicit operator decimal?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return decimal.Parse(cell.Value); } + public static implicit operator DateTime(TableCell cell) { - if (cell == null) throw new ArgumentNullException("TableCell"); + if (cell == null) + throw new ArgumentNullException("TableCell"); return new DateTime(1900, 1, 1).AddDays(int.Parse(cell.Value) - 2); } + public static implicit operator DateTime?(TableCell cell) { - if (cell == null) return null; + if (cell == null) + return null; return new DateTime(1900, 1, 1).AddDays(int.Parse(cell.Value) - 2); } } @@ -250,48 +310,54 @@ public class Row public XElement RowElement { get; set; } public string RowId { get; set; } public string Spans { get; set; } + public List Cells() { XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; var doc = (SpreadsheetDocument)Parent.OpenXmlPackage; var sharedStringTable = doc.WorkbookPart.SharedStringTablePart; var cells = this.RowElement.Elements(S.c); - var r = cells - .Select(cell => { - var cellType = (string)cell.Attribute("t"); - var sharedString = cellType == "s" ? - sharedStringTable - .GetXDocument() - .Root - .Elements(s + "si") - .Skip((int)cell.Element(s + "v")) - .First() - .Descendants(s + "t") - .StringConcatenate(e => (string)e) + var r = cells.Select(cell => + { + var cellType = (string)cell.Attribute("t"); + var sharedString = + cellType == "s" + ? sharedStringTable + .GetXDocument() + .Root.Elements(s + "si") + .Skip((int)cell.Element(s + "v")) + .First() + .Descendants(s + "t") + .StringConcatenate(e => (string)e) : null; - var column = (string)cell.Attribute("r"); - var columnAddress = column.Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9').First(); - var columnIndex = XlsxTables.ColumnAddressToIndex(columnAddress); - var newCell = new Cell(this) - { - CellElement = cell, - Row = (string)RowElement.Attribute("r"), - Column = column, - ColumnAddress = columnAddress, - ColumnIndex = columnIndex, - Type = cellType, - Formula = (string)cell.Element(S.f), - Style = (int?)cell.Attribute("s"), - Value = (string)cell.Element(S.v), - SharedString = sharedString - }; - return newCell; - }); + var column = (string)cell.Attribute("r"); + var columnAddress = column.Split('0', '1', '2', '3', '4', '5', '6', '7', '8', '9').First(); + var columnIndex = XlsxTables.ColumnAddressToIndex(columnAddress); + var newCell = new Cell(this) + { + CellElement = cell, + Row = (string)RowElement.Attribute("r"), + Column = column, + ColumnAddress = columnAddress, + ColumnIndex = columnIndex, + Type = cellType, + Formula = (string)cell.Element(S.f), + Style = (int?)cell.Attribute("s"), + Value = (string)cell.Element(S.v), + SharedString = sharedString, + }; + return newCell; + }); var ra = r.ToList(); return ra; } + public WorksheetPart Parent { get; set; } - public Row(WorksheetPart parent) { Parent = parent; } + + public Row(WorksheetPart parent) + { + Parent = parent; + } } public class Cell @@ -307,7 +373,11 @@ public class Cell public int? Style { get; set; } public string SharedString { get; set; } public Row Parent { get; set; } - public Cell(Row parent) { Parent = parent; } + + public Cell(Row parent) + { + Parent = parent; + } } public static class XlsxTables @@ -315,33 +385,39 @@ public static class XlsxTables public static IEnumerable Tables(this SpreadsheetDocument spreadsheet) { foreach (var worksheetPart in spreadsheet.WorkbookPart.WorksheetParts) - foreach (var table in worksheetPart.TableDefinitionParts) - { - var tableDefDoc = table.GetXDocument(); + foreach (var table in worksheetPart.TableDefinitionParts) + { + var tableDefDoc = table.GetXDocument(); - var t = new Table(worksheetPart) - { - Id = (int)tableDefDoc.Root.Attribute("id"), - TableName = (string)tableDefDoc.Root.Attribute("name"), - DisplayName = (string)tableDefDoc.Root.Attribute("displayName"), - TableStyleInfo = tableDefDoc.Root.Element(S.tableStyleInfo), - Ref = (string)tableDefDoc.Root.Attribute("ref"), - TotalsRowCount = (int?)tableDefDoc.Root.Attribute("totalsRowCount"), - //HeaderRowCount = (int?)tableDefDoc.Root.Attribute("headerRowCount"), - HeaderRowCount = 1, // currently there always is a header row - TableType = (string)tableDefDoc.Root.Attribute("tableType"), - TableDefinitionPart = table - }; - ParseRange(t.Ref, out var leftColumn, out var topRow, out var rightColumn, out var bottomRow); - t.LeftColumn = leftColumn; - t.TopRow = topRow; - t.RightColumn = rightColumn; - t.BottomRow = bottomRow; - yield return t; - } + var t = new Table(worksheetPart) + { + Id = (int)tableDefDoc.Root.Attribute("id"), + TableName = (string)tableDefDoc.Root.Attribute("name"), + DisplayName = (string)tableDefDoc.Root.Attribute("displayName"), + TableStyleInfo = tableDefDoc.Root.Element(S.tableStyleInfo), + Ref = (string)tableDefDoc.Root.Attribute("ref"), + TotalsRowCount = (int?)tableDefDoc.Root.Attribute("totalsRowCount"), + //HeaderRowCount = (int?)tableDefDoc.Root.Attribute("headerRowCount"), + HeaderRowCount = 1, // currently there always is a header row + TableType = (string)tableDefDoc.Root.Attribute("tableType"), + TableDefinitionPart = table, + }; + ParseRange(t.Ref, out var leftColumn, out var topRow, out var rightColumn, out var bottomRow); + t.LeftColumn = leftColumn; + t.TopRow = topRow; + t.RightColumn = rightColumn; + t.BottomRow = bottomRow; + yield return t; + } } - public static void ParseRange(string theRef, out int leftColumn, out int topRow, out int rightColumn, out int bottomRow) + public static void ParseRange( + string theRef, + out int leftColumn, + out int topRow, + out int rightColumn, + out int bottomRow + ) { // C5:E7 var spl = theRef.Split(':'); @@ -356,8 +432,7 @@ public static void ParseRange(string theRef, out int leftColumn, out int topRow, bottomRow = int.Parse(refEndSplit[1]); } - public static Table Table(this SpreadsheetDocument spreadsheet, - string tableName) + public static Table Table(this SpreadsheetDocument spreadsheet, string tableName) { return spreadsheet.Tables().FirstOrDefault(t => t.TableName.ToLower() == tableName.ToLower()); } @@ -367,8 +442,7 @@ public static IEnumerable Rows(this WorksheetPart worksheetPart) XNamespace s = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; var rows = worksheetPart .GetXDocument() - .Root - .Elements(S.sheetData) + .Root.Elements(S.sheetData) .Elements(S.row) .Select(r => { @@ -376,7 +450,7 @@ public static IEnumerable Rows(this WorksheetPart worksheetPart) { RowElement = r, RowId = (string)r.Attribute("r"), - Spans = (string)r.Attribute("spans") + Spans = (string)r.Attribute("spans"), }; return row; }); @@ -391,10 +465,7 @@ public static string[] SplitAddress(string address) break; if (i == address.Length) throw new FileFormatException("Invalid spreadsheet. Bad cell address."); - return new[] { - address.Substring(0, i), - address.Substring(i) - }; + return new[] { address.Substring(0, i), address.Substring(i) }; } public static string IndexToColumnAddress(int index) @@ -410,8 +481,7 @@ public static string IndexToColumnAddress(int index) var i = index - 26; var i1 = i / 26; var i2 = i % 26; - var s = new string((char)('A' + i1), 1) + - new string((char)('A' + i2), 1); + var s = new string((char)('A' + i1), 1) + new string((char)('A' + i2), 1); return s; } if (index < 18278) @@ -421,9 +491,8 @@ public static string IndexToColumnAddress(int index) i = i - i1 * 676; var i2 = i / 26; var i3 = i % 26; - var s = new string((char)('A' + i1), 1) + - new string((char)('A' + i2), 1) + - new string((char)('A' + i3), 1); + var s = + new string((char)('A' + i1), 1) + new string((char)('A' + i2), 1) + new string((char)('A' + i3), 1); return s; } throw new Exception("Invalid column address"); diff --git a/Clippit/FieldRetriever.cs b/Clippit/FieldRetriever.cs index 44c0877d..e5d4140b 100644 --- a/Clippit/FieldRetriever.cs +++ b/Clippit/FieldRetriever.cs @@ -12,7 +12,6 @@ public class FieldRetriever { public static string InstrText(XElement root, int id) { - XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; #if false @@ -54,14 +53,16 @@ public static string InstrText(XElement root, int id) if (g.Key == false) { return g.Select(e => - { - var s = e.Annotation>(); - var stackElement = s.FirstOrDefault(z => z.Id == id); - if (stackElement.FieldElementType == FieldElementTypeEnum.InstrText && - e.Name == w + "instrText") - return e.Value; - return ""; - }) + { + var s = e.Annotation>(); + var stackElement = s.FirstOrDefault(z => z.Id == id); + if ( + stackElement.FieldElementType == FieldElementTypeEnum.InstrText + && e.Name == w + "instrText" + ) + return e.Value; + return ""; + }) .StringConcatenate(); } else @@ -85,11 +86,7 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) var root = part.GetXDocument().Root; var r = root.DescendantsAndSelf() .Rollup( - new FieldElementTypeStack - { - Id = 0, - FiStack = null, - }, + new FieldElementTypeStack { Id = 0, FiStack = null }, (e, s) => { if (e.Name == w + "fldChar") @@ -106,13 +103,11 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) { Id = s.Id + 1, FieldElementType = FieldElementTypeEnum.Begin, - }); - return new FieldElementTypeStack - { - Id = s.Id + 1, - FiStack = fis, - }; - }; + } + ); + return new FieldElementTypeStack { Id = s.Id + 1, FiStack = fis }; + } + ; if (e.Attribute(w + "fldCharType").Value == "separate") { var fis = new Stack(s.FiStack.Reverse()); @@ -122,22 +117,15 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) { Id = wfi.Id, FieldElementType = FieldElementTypeEnum.Separate, - }); - return new FieldElementTypeStack - { - Id = s.Id, - FiStack = fis, - }; + } + ); + return new FieldElementTypeStack { Id = s.Id, FiStack = fis }; } if (e.Attribute(w + "fldCharType").Value == "end") { var fis = new Stack(s.FiStack.Reverse()); var wfi = fis.Pop(); - return new FieldElementTypeStack - { - Id = s.Id, - FiStack = fis, - }; + return new FieldElementTypeStack { Id = s.Id, FiStack = fis }; } } if (s.FiStack == null || s.FiStack.Count == 0) @@ -152,12 +140,9 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) { Id = wfi2.Id, FieldElementType = FieldElementTypeEnum.InstrText, - }); - return new FieldElementTypeStack - { - Id = s.Id, - FiStack = fis, - }; + } + ); + return new FieldElementTypeStack { Id = s.Id, FiStack = fis }; } if (wfi3.FieldElementType == FieldElementTypeEnum.Separate) { @@ -168,12 +153,9 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) { Id = wfi2.Id, FieldElementType = FieldElementTypeEnum.Result, - }); - return new FieldElementTypeStack - { - Id = s.Id, - FiStack = fis, - }; + } + ); + return new FieldElementTypeStack { Id = s.Id, FiStack = fis }; } if (wfi3.FieldElementType == FieldElementTypeEnum.End) { @@ -181,23 +163,24 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) fis.Pop(); if (!fis.Any()) fis = null; - return new FieldElementTypeStack - { - Id = s.Id, - FiStack = fis, - }; + return new FieldElementTypeStack { Id = s.Id, FiStack = fis }; } return s; - }); - var elementPlusInfo = root.DescendantsAndSelf().PtZip(r, (t1, t2) => - { - return new - { - Element = t1, - Id = t2.Id, - WmlFieldInfoStack = t2.FiStack, - }; - }); + } + ); + var elementPlusInfo = root.DescendantsAndSelf() + .PtZip( + r, + (t1, t2) => + { + return new + { + Element = t1, + Id = t2.Id, + WmlFieldInfoStack = t2.FiStack, + }; + } + ); foreach (var item in elementPlusInfo) { if (item.WmlFieldInfoStack != null) @@ -225,7 +208,7 @@ public static void AnnotateWithFieldInfo(OpenXmlPart part) { var s = desc.Annotation>(); - if (s != null ) + if (s != null) { foreach (var item in s) { @@ -362,10 +345,12 @@ public static FieldInfo ParseField(string field) var fieldType = field.TrimStart().Split(' ').FirstOrDefault(); if (fieldType == null) return emptyField; - if (fieldType.ToUpper() != "HYPERLINK" && - fieldType.ToUpper() != "REF" && - fieldType.ToUpper() != "SEQ" && - fieldType.ToUpper() != "STYLEREF") + if ( + fieldType.ToUpper() != "HYPERLINK" + && fieldType.ToUpper() != "REF" + && fieldType.ToUpper() != "SEQ" + && fieldType.ToUpper() != "STYLEREF" + ) return emptyField; var tokens = GetTokens(field); if (tokens.Length == 0) diff --git a/Clippit/Html/HtmlToWmlConverter.cs b/Clippit/Html/HtmlToWmlConverter.cs index f5e0db11..af7ee398 100644 --- a/Clippit/Html/HtmlToWmlConverter.cs +++ b/Clippit/Html/HtmlToWmlConverter.cs @@ -22,12 +22,30 @@ public class HtmlToWmlConverterSettings public string DefaultBlockContentMargin; public string BaseUriForImages; - public Twip PageWidthTwips { get { return (long)SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault(); } } - public Twip PageMarginLeftTwips { get { return (long)SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); } } - public Twip PageMarginRightTwips { get { return (long)SectPr.Elements(W.pgMar).Attributes(W.right).FirstOrDefault(); } } - public Emu PageWidthEmus { get { return Emu.TwipsToEmus(PageWidthTwips); } } - public Emu PageMarginLeftEmus { get { return Emu.TwipsToEmus(PageMarginLeftTwips); } } - public Emu PageMarginRightEmus { get { return Emu.TwipsToEmus(PageMarginRightTwips); } } + public Twip PageWidthTwips + { + get { return (long)SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault(); } + } + public Twip PageMarginLeftTwips + { + get { return (long)SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); } + } + public Twip PageMarginRightTwips + { + get { return (long)SectPr.Elements(W.pgMar).Attributes(W.right).FirstOrDefault(); } + } + public Emu PageWidthEmus + { + get { return Emu.TwipsToEmus(PageWidthTwips); } + } + public Emu PageMarginLeftEmus + { + get { return Emu.TwipsToEmus(PageMarginLeftTwips); } + } + public Emu PageMarginRightEmus + { + get { return Emu.TwipsToEmus(PageMarginRightTwips); } + } } public class HtmlToWmlConverter @@ -37,7 +55,8 @@ public static WmlDocument ConvertHtmlToWml( string authorCss, string userCss, XElement xhtml, - HtmlToWmlConverterSettings settings) + HtmlToWmlConverterSettings settings + ) { return HtmlToWmlConverterCore.ConvertHtmlToWml(defaultCss, authorCss, userCss, xhtml, settings, null, null); } @@ -49,12 +68,22 @@ public static WmlDocument ConvertHtmlToWml( XElement xhtml, HtmlToWmlConverterSettings settings, WmlDocument emptyDocument, - string annotatedHtmlDumpFileName) + string annotatedHtmlDumpFileName + ) { - return HtmlToWmlConverterCore.ConvertHtmlToWml(defaultCss, authorCss, userCss, xhtml, settings, emptyDocument, annotatedHtmlDumpFileName); + return HtmlToWmlConverterCore.ConvertHtmlToWml( + defaultCss, + authorCss, + userCss, + xhtml, + settings, + emptyDocument, + annotatedHtmlDumpFileName + ); } - private static readonly string s_Blank_wml_base64 = @"UEsDBBQABgAIAAAAIQAJJIeCgQEAAI4FAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC + private static readonly string s_Blank_wml_base64 = + @"UEsDBBQABgAIAAAAIQAJJIeCgQEAAI4FAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -297,10 +326,14 @@ public static WmlDocument ConvertHtmlToWml( public static WmlDocument EmptyDocument { - get { + get + { if (s_EmptyDocument == null) { - s_EmptyDocument = new WmlDocument("EmptyDocument.docx", Convert.FromBase64String(s_Blank_wml_base64)); + s_EmptyDocument = new WmlDocument( + "EmptyDocument.docx", + Convert.FromBase64String(s_Blank_wml_base64) + ); } return s_EmptyDocument; } @@ -325,41 +358,69 @@ public static HtmlToWmlConverterSettings GetDefaultSettings(WmlDocument wmlDocum settings.MinorLatinFont = "Times New Roman"; settings.DefaultFontSize = 12d; settings.DefaultBlockContentMargin = "auto"; - settings.DefaultSpacingElement = new XElement(W.spacing, + settings.DefaultSpacingElement = new XElement( + W.spacing, new XAttribute(W.before, 100), new XAttribute(W.beforeAutospacing, 1), new XAttribute(W.after, 100), new XAttribute(W.afterAutospacing, 1), new XAttribute(W.line, 240), - new XAttribute(W.lineRule, "auto")); - settings.DefaultSpacingElementForParagraphsInTables = new XElement(W.spacing, + new XAttribute(W.lineRule, "auto") + ); + settings.DefaultSpacingElementForParagraphsInTables = new XElement( + W.spacing, new XAttribute(W.before, 100), new XAttribute(W.beforeAutospacing, 1), new XAttribute(W.after, 100), new XAttribute(W.afterAutospacing, 1), new XAttribute(W.line, 240), - new XAttribute(W.lineRule, "auto")); + new XAttribute(W.lineRule, "auto") + ); var mXDoc = wDoc.MainDocumentPart.GetXDocument(); var existingSectPr = mXDoc.Root.Descendants(W.sectPr).FirstOrDefault(); - settings.SectPr = new XElement(W.sectPr, - existingSectPr.Elements(W.pgSz), - existingSectPr.Elements(W.pgMar)); + settings.SectPr = new XElement(W.sectPr, existingSectPr.Elements(W.pgSz), existingSectPr.Elements(W.pgMar)); return settings; } - private static void GetDefaultFontInfo(WordprocessingDocument wDoc, out string majorLatinFont, out string minorLatinFont, out double defaultFontSize) + private static void GetDefaultFontInfo( + WordprocessingDocument wDoc, + out string majorLatinFont, + out string minorLatinFont, + out double defaultFontSize + ) { if (wDoc.MainDocumentPart.ThemePart != null) { - var fontScheme = wDoc.MainDocumentPart.ThemePart.GetXDocument().Root.Elements(A.themeElements).Elements(A.fontScheme).FirstOrDefault(); + var fontScheme = wDoc + .MainDocumentPart.ThemePart.GetXDocument() + .Root.Elements(A.themeElements) + .Elements(A.fontScheme) + .FirstOrDefault(); if (fontScheme != null) { - majorLatinFont = (string)fontScheme.Elements(A.majorFont).Elements(A.latin).Attributes(NoNamespace.typeface).FirstOrDefault(); - minorLatinFont = (string)fontScheme.Elements(A.minorFont).Elements(A.latin).Attributes(NoNamespace.typeface).FirstOrDefault(); - var defaultFontSizeString = (string)wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument().Root.Elements(W.docDefaults) - .Elements(W.rPrDefault).Elements(W.rPr).Elements(W.sz).Attributes(W.val).FirstOrDefault(); + majorLatinFont = (string) + fontScheme + .Elements(A.majorFont) + .Elements(A.latin) + .Attributes(NoNamespace.typeface) + .FirstOrDefault(); + minorLatinFont = (string) + fontScheme + .Elements(A.minorFont) + .Elements(A.latin) + .Attributes(NoNamespace.typeface) + .FirstOrDefault(); + var defaultFontSizeString = (string) + wDoc + .MainDocumentPart.StyleDefinitionsPart.GetXDocument() + .Root.Elements(W.docDefaults) + .Elements(W.rPrDefault) + .Elements(W.rPr) + .Elements(W.sz) + .Attributes(W.val) + .FirstOrDefault(); if (defaultFontSizeString != null) { if (double.TryParse(defaultFontSizeString, out var dfs)) @@ -382,7 +443,8 @@ public static string CleanUpCss(string css) if (css == null) return ""; css = css.Trim(); - var cleanCss = Regex.Split(css, "\r\n|\r|\n") + var cleanCss = Regex + .Split(css, "\r\n|\r|\n") .Where(l => { var lTrim = l.Trim(); @@ -390,7 +452,7 @@ public static string CleanUpCss(string css) return false; return true; }) - .Select(l => l + Environment.NewLine ) + .Select(l => l + Environment.NewLine) .StringConcatenate(); return cleanCss; } diff --git a/Clippit/Html/HtmlToWmlConverterCore.cs b/Clippit/Html/HtmlToWmlConverterCore.cs index 51afa1ef..6c785a27 100644 --- a/Clippit/Html/HtmlToWmlConverterCore.cs +++ b/Clippit/Html/HtmlToWmlConverterCore.cs @@ -137,7 +137,8 @@ public static WmlDocument ConvertHtmlToWml( string authorCss, string userCss, XElement xhtml, - HtmlToWmlConverterSettings settings) + HtmlToWmlConverterSettings settings + ) { return ConvertHtmlToWml(defaultCss, authorCss, userCss, xhtml, settings, null, null); } @@ -149,7 +150,8 @@ public static WmlDocument ConvertHtmlToWml( XElement xhtml, HtmlToWmlConverterSettings settings, WmlDocument emptyDocument, - string annotatedHtmlDumpFileName) + string annotatedHtmlDumpFileName + ) { if (emptyDocument == null) emptyDocument = HtmlToWmlConverter.EmptyDocument; @@ -173,7 +175,8 @@ public static WmlDocument ConvertHtmlToWml( out var defaultCssDoc, out var authorCssDoc, out var userCssDoc, - annotatedHtmlDumpFileName); + annotatedHtmlDumpFileName + ); using var streamDoc = new OpenXmlMemoryStreamDocument(emptyDocument); using (var wDoc = streamDoc.GetWordprocessingDocument()) @@ -191,15 +194,16 @@ public static WmlDocument ConvertHtmlToWml( return newWmlDocument; } - private static object TransformToLower(XNode node) { var element = node as XElement; if (element != null) { - var e = new XElement(element.Name.LocalName.ToLower(), + var e = new XElement( + element.Name.LocalName.ToLower(), element.Attributes().Select(a => new XAttribute(a.Name.LocalName.ToLower(), a.Value)), - element.Nodes().Select(n => TransformToLower(n))); + element.Nodes().Select(n => TransformToLower(n)) + ); return e; } return node; @@ -209,22 +213,19 @@ private static XElement AddPseudoCells(XElement html) { while (true) { - var rowSpanCell = html - .Descendants(XhtmlNoNamespace.td) - .FirstOrDefault(td => td.Attribute(XhtmlNoNamespace.rowspan) != null && td.Attribute("HtmlToWmlVMergeRestart") == null); + var rowSpanCell = html.Descendants(XhtmlNoNamespace.td) + .FirstOrDefault(td => + td.Attribute(XhtmlNoNamespace.rowspan) != null && td.Attribute("HtmlToWmlVMergeRestart") == null + ); if (rowSpanCell == null) break; - rowSpanCell.Add( - new XAttribute("HtmlToWmlVMergeRestart", "true")); + rowSpanCell.Add(new XAttribute("HtmlToWmlVMergeRestart", "true")); var colNumber = rowSpanCell.ElementsBeforeSelf(XhtmlNoNamespace.td).Count(); var numberPseudoToAdd = (int)rowSpanCell.Attribute(XhtmlNoNamespace.rowspan) - 1; var tr = rowSpanCell.Ancestors(XhtmlNoNamespace.tr).FirstOrDefault(); if (tr == null) throw new OpenXmlPowerToolsException("Invalid HTML - td does not have parent tr"); - var rowsToAddTo = tr - .ElementsAfterSelf(XhtmlNoNamespace.tr) - .Take(numberPseudoToAdd) - .ToList(); + var rowsToAddTo = tr.ElementsAfterSelf(XhtmlNoNamespace.tr).Take(numberPseudoToAdd).ToList(); foreach (var rowToAddTo in rowsToAddTo) { if (colNumber > 0) @@ -235,23 +236,23 @@ private static XElement AddPseudoCells(XElement html) .FirstOrDefault(); if (tdToAddAfter == null) { - tdToAddAfter = rowToAddTo.Elements(XhtmlNoNamespace.td) - .LastOrDefault(); + tdToAddAfter = rowToAddTo.Elements(XhtmlNoNamespace.td).LastOrDefault(); } - var td = new XElement(XhtmlNoNamespace.td, + var td = new XElement( + XhtmlNoNamespace.td, rowSpanCell.Attributes(), - new XAttribute("HtmlToWmlVMergeNoRestart", "true")); + new XAttribute("HtmlToWmlVMergeNoRestart", "true") + ); tdToAddAfter.AddAfterSelf(td); } else { - var tdToAddBefore = rowToAddTo - .Elements(XhtmlNoNamespace.td) - .Skip(colNumber) - .FirstOrDefault(); - var td = new XElement(XhtmlNoNamespace.td, + var tdToAddBefore = rowToAddTo.Elements(XhtmlNoNamespace.td).Skip(colNumber).FirstOrDefault(); + var td = new XElement( + XhtmlNoNamespace.td, rowSpanCell.Attributes(), - new XAttribute("HtmlToWmlVMergeNoRestart", "true")); + new XAttribute("HtmlToWmlVMergeNoRestart", "true") + ); tdToAddBefore.AddBeforeSelf(td); } } @@ -269,28 +270,41 @@ public class NumberedItemAnnotation private static void AnnotateOlUl(WordprocessingDocument wDoc, XElement html) { NumberingUpdater.GetNextNumId(wDoc, out var numId); - foreach (var item in html.DescendantsAndSelf().Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul)) - { - var parentOlUl = item.Ancestors().Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul).LastOrDefault(); + foreach ( + var item in html.DescendantsAndSelf() + .Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul) + ) + { + var parentOlUl = item.Ancestors() + .Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul) + .LastOrDefault(); int numIdToUse; if (parentOlUl != null) numIdToUse = parentOlUl.Annotation().numId; else numIdToUse = numId++; var lst = CssApplier.GetComputedPropertyValue(null, item, "list-style-type", null).ToString(); - item.AddAnnotation(new NumberedItemAnnotation - { - numId = numIdToUse, - ilvl = item.Ancestors().Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul).Count(), - listStyleType = lst, - }); + item.AddAnnotation( + new NumberedItemAnnotation + { + numId = numIdToUse, + ilvl = item.Ancestors() + .Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul) + .Count(), + listStyleType = lst, + } + ); } } - private static void UpdateMainDocumentPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings) + private static void UpdateMainDocumentPart( + WordprocessingDocument wDoc, + XElement html, + HtmlToWmlConverterSettings settings + ) { var xDoc = XDocument.Parse( -@""); + mc:Ignorable='w14 wp14'/>" + ); - var body = new XElement(W.body, - Transform(html, settings, wDoc, NextExpected.Paragraph, false), - settings.SectPr); + var body = new XElement( + W.body, + Transform(html, settings, wDoc, NextExpected.Paragraph, false), + settings.SectPr + ); AddNonBreakingSpacesForSpansWithWidth(wDoc, body); body = (XElement)TransformAndOrderElements(body); @@ -327,22 +344,30 @@ private static object TransformWhiteSpaceInPreCodeTtKbdSamp(XNode node, bool inP { if (element.Name == XhtmlNoNamespace.pre) { - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, true, false))); + element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, true, false)) + ); } - if (element.Name == XhtmlNoNamespace.code || - element.Name == XhtmlNoNamespace.tt || - element.Name == XhtmlNoNamespace.kbd || - element.Name == XhtmlNoNamespace.samp) + if ( + element.Name == XhtmlNoNamespace.code + || element.Name == XhtmlNoNamespace.tt + || element.Name == XhtmlNoNamespace.kbd + || element.Name == XhtmlNoNamespace.samp + ) { - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, true))); + element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, true)) + ); } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, false))); + element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, false)) + ); } var xt = node as XText; if (xt != null && inPre) @@ -537,98 +562,144 @@ private static object TransformAndOrderElements(XNode node) if (element != null) { if (element.Name == W.pPr) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_pPr.ContainsKey(e.Name)) - return Order_pPr[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_pPr.ContainsKey(e.Name)) + return Order_pPr[e.Name]; + return 999; + }) + ); if (element.Name == W.rPr) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_rPr.ContainsKey(e.Name)) - return Order_rPr[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_rPr.ContainsKey(e.Name)) + return Order_rPr[e.Name]; + return 999; + }) + ); if (element.Name == W.tblPr) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_tblPr.ContainsKey(e.Name)) - return Order_tblPr[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_tblPr.ContainsKey(e.Name)) + return Order_tblPr[e.Name]; + return 999; + }) + ); if (element.Name == W.tcPr) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_tcPr.ContainsKey(e.Name)) - return Order_tcPr[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_tcPr.ContainsKey(e.Name)) + return Order_tcPr[e.Name]; + return 999; + }) + ); if (element.Name == W.tcBorders) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_tcBorders.ContainsKey(e.Name)) - return Order_tcBorders[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_tcBorders.ContainsKey(e.Name)) + return Order_tcBorders[e.Name]; + return 999; + }) + ); if (element.Name == W.tblBorders) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_tblBorders.ContainsKey(e.Name)) - return Order_tblBorders[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_tblBorders.ContainsKey(e.Name)) + return Order_tblBorders[e.Name]; + return 999; + }) + ); if (element.Name == W.pBdr) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e => - { - if (Order_pBdr.ContainsKey(e.Name)) - return Order_pBdr[e.Name]; - return 999; - })); + element + .Elements() + .Select(e => (XElement)TransformAndOrderElements(e)) + .OrderBy(e => + { + if (Order_pBdr.ContainsKey(e.Name)) + return Order_pBdr[e.Name]; + return 999; + }) + ); if (element.Name == W.p) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), element.Elements(W.pPr).Select(e => (XElement)TransformAndOrderElements(e)), - element.Elements().Where(e => e.Name != W.pPr).Select(e => (XElement)TransformAndOrderElements(e))); + element + .Elements() + .Where(e => e.Name != W.pPr) + .Select(e => (XElement)TransformAndOrderElements(e)) + ); if (element.Name == W.r) - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), element.Elements(W.rPr).Select(e => (XElement)TransformAndOrderElements(e)), - element.Elements().Where(e => e.Name != W.rPr).Select(e => (XElement)TransformAndOrderElements(e))); + element + .Elements() + .Where(e => e.Name != W.rPr) + .Select(e => (XElement)TransformAndOrderElements(e)) + ); - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => TransformAndOrderElements(n))); + element.Nodes().Select(n => TransformAndOrderElements(n)) + ); } return node; } private static void AddNonBreakingSpacesForSpansWithWidth(WordprocessingDocument wDoc, XElement body) { - var runsWithWidth = body - .Descendants(W.r) + var runsWithWidth = body.Descendants(W.r) .Where(r => r.Attribute(PtOpenXml.HtmlToWmlCssWidth) != null) .ToList(); foreach (var run in runsWithWidth) @@ -637,8 +708,9 @@ private static void AddNonBreakingSpacesForSpansWithWidth(WordprocessingDocument var pPr = p != null ? p.Element(W.pPr) : null; var rPr = run.Element(W.rPr); var rFonts = rPr != null ? rPr.Element(W.rFonts) : null; - var str = run.Descendants(W.t).Select(t => (string) t).StringConcatenate(); - if ((pPr == null) || (rPr == null) || (rFonts == null) || (str == "")) continue; + var str = run.Descendants(W.t).Select(t => (string)t).StringConcatenate(); + if ((pPr == null) || (rPr == null) || (rFonts == null) || (str == "")) + continue; AdjustFontAttributes(wDoc, run, pPr, rPr); var csa = new CharStyleAttributes(pPr, rPr); @@ -652,19 +724,19 @@ private static void AddNonBreakingSpacesForSpansWithWidth(WordprocessingDocument switch (ft) { case FontType.Ascii: - fontType = (string) rFonts.Attribute(W.ascii); + fontType = (string)rFonts.Attribute(W.ascii); languageType = "western"; break; case FontType.HAnsi: - fontType = (string) rFonts.Attribute(W.hAnsi); + fontType = (string)rFonts.Attribute(W.hAnsi); languageType = "western"; break; case FontType.EastAsia: - fontType = (string) rFonts.Attribute(W.eastAsia); + fontType = (string)rFonts.Attribute(W.eastAsia); languageType = "eastAsia"; break; case FontType.CS: - fontType = (string) rFonts.Attribute(W.cs); + fontType = (string)rFonts.Attribute(W.cs); languageType = "bidi"; break; } @@ -694,24 +766,23 @@ private static void AddNonBreakingSpacesForSpansWithWidth(WordprocessingDocument var pixWidth = (int?)WordprocessingMLUtil.CalcWidthOfRunInPixels(run) ?? 0; // calc width of non breaking spaces - var npSpRun = new XElement(W.r, - run.Attributes(), - run.Elements(W.rPr), - new XElement(W.t, "\u00a0")); + var npSpRun = new XElement(W.r, run.Attributes(), run.Elements(W.rPr), new XElement(W.t, "\u00a0")); var nbSpWidth = (int?)WordprocessingMLUtil.CalcWidthOfRunInPixels(npSpRun) ?? 0; if (nbSpWidth == 0) continue; // get HtmlToWmlCssWidth attribute - var cssWidth = (string) run.Attribute(PtOpenXml.HtmlToWmlCssWidth); - if (!cssWidth.EndsWith("pt")) continue; + var cssWidth = (string)run.Attribute(PtOpenXml.HtmlToWmlCssWidth); + if (!cssWidth.EndsWith("pt")) + continue; cssWidth = cssWidth.Substring(0, cssWidth.Length - 2); - if (!decimal.TryParse(cssWidth, out var cssWidthInDecimal)) continue; + if (!decimal.TryParse(cssWidth, out var cssWidthInDecimal)) + continue; // calculate the number of non-breaking spaces to add - var cssWidthInPixels = cssWidthInDecimal/72*96; - var numberOfNpSpToAdd = (int) ((cssWidthInPixels - pixWidth)/nbSpWidth); + var cssWidthInPixels = cssWidthInDecimal / 72 * 96; + var numberOfNpSpToAdd = (int)((cssWidthInPixels - pixWidth) / nbSpWidth); if (numberOfNpSpToAdd > 0) run.Add(new XElement(W.t, "".PadRight(numberOfNpSpToAdd, '\u00a0'))); } @@ -732,25 +803,23 @@ private static object NormalizeTransform(XNode node) { if (element.Name == W.p && element.Elements().Any(c => c.Name == W.p || c.Name == W.tbl)) { - var groupedChildren = element.Elements() - .GroupAdjacent(e => e.Name == W.p || e.Name == W.tbl); - var newContent = groupedChildren - .Select(g => + var groupedChildren = element.Elements().GroupAdjacent(e => e.Name == W.p || e.Name == W.tbl); + var newContent = groupedChildren.Select(g => + { + if (g.Key == false) { - if (g.Key == false) - { - var paragraph = new XElement(W.p, - element.Elements(W.pPr), - g.Where(gc => gc.Name != W.pPr)); - return (object)paragraph; - } - return g.Select(n => NormalizeTransform(n)); - }); + var paragraph = new XElement(W.p, element.Elements(W.pPr), g.Where(gc => gc.Name != W.pPr)); + return (object)paragraph; + } + return g.Select(n => NormalizeTransform(n)); + }); return newContent; } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => NormalizeTransform(n))); + element.Nodes().Select(n => NormalizeTransform(n)) + ); } return node; } @@ -762,7 +831,13 @@ private enum NextExpected SubRun, } - private static object Transform(XNode node, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, NextExpected nextExpected, bool preserveWhiteSpace) + private static object Transform( + XNode node, + HtmlToWmlConverterSettings settings, + WordprocessingDocument wDoc, + NextExpected nextExpected, + bool preserveWhiteSpace + ) { var element = node as XElement; if (element != null) @@ -781,9 +856,7 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, catch (UriFormatException) { var rPr = GetRunProperties(element, settings); - var run = new XElement(W.r, - rPr, - new XElement(W.t, element.Value)); + var run = new XElement(W.r, rPr, new XElement(W.t, element.Value)); return new[] { run }; } @@ -792,19 +865,28 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, wDoc.MainDocumentPart.AddHyperlinkRelationship(uri, true, rId); if (element.Element(XhtmlNoNamespace.img) != null) { - var imageTransformed = element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)).OfType(); + var imageTransformed = element + .Nodes() + .Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)) + .OfType(); var newImageTransformed = imageTransformed .Select(i => { if (i.Elements(W.drawing).Any()) { var newRun = new XElement(i); - var docPr = newRun.Elements(W.drawing).Elements(WP.inline).Elements(WP.docPr).FirstOrDefault(); + var docPr = newRun + .Elements(W.drawing) + .Elements(WP.inline) + .Elements(WP.docPr) + .FirstOrDefault(); if (docPr != null) { - var hlinkClick = new XElement(A.hlinkClick, + var hlinkClick = new XElement( + A.hlinkClick, new XAttribute(R.id, rId), - new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName)); + new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName) + ); docPr.Add(hlinkClick); } return newRun; @@ -816,11 +898,11 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, } var rPr = GetRunProperties(element, settings); - var hyperlink = new XElement(W.hyperlink, + var hyperlink = new XElement( + W.hyperlink, new XAttribute(R.id, rId), - new XElement(W.r, - rPr, - new XElement(W.t, element.Value))); + new XElement(W.r, rPr, new XElement(W.t, element.Value)) + ); return new[] { hyperlink }; } } @@ -835,23 +917,37 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, if (element.Name == XhtmlNoNamespace.caption) { - return new XElement(W.tr, + return new XElement( + W.tr, GetTableRowProperties(element), - new XElement(W.tc, + new XElement( + W.tc, GetCellPropertiesForCaption(element), - element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)))); + element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)) + ) + ); } if (element.Name == XhtmlNoNamespace.div) { if (nextExpected == NextExpected.Paragraph) { - if (element.Descendants().Any(d => d.Name == XhtmlNoNamespace.h1 || - d.Name == XhtmlNoNamespace.li || - d.Name == XhtmlNoNamespace.p || - d.Name == XhtmlNoNamespace.table)) + if ( + element + .Descendants() + .Any(d => + d.Name == XhtmlNoNamespace.h1 + || d.Name == XhtmlNoNamespace.li + || d.Name == XhtmlNoNamespace.p + || d.Name == XhtmlNoNamespace.table + ) + ) { - return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); } else { @@ -860,12 +956,16 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, } else { - return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); } } if (element.Name == XhtmlNoNamespace.em) - return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace)); var hi = HeadingTagMap.FirstOrDefault(htm => htm.Name == element.Name); if (hi != null) @@ -877,13 +977,15 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, { var i = GetNextRectId(); var hr = XElement.Parse( - @" - - "); + " + ); hr.Attributes().Where(a => a.IsNamespaceDeclaration).Remove(); return hr; } if (element.Name == XhtmlNoNamespace.html) - return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); if (element.Name == XhtmlNoNamespace.i) return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); @@ -910,9 +1015,11 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, { if (element.Parent.Name == XhtmlNoNamespace.body) { - var para = new XElement(W.p, + var para = new XElement( + W.p, GetParagraphPropertiesForImage(), - TransformImageToWml(element, settings, wDoc)); + TransformImageToWml(element, settings, wDoc) + ); return para; } else @@ -928,7 +1035,9 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, } if (element.Name == XhtmlNoNamespace.ol) - return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); if (element.Name == XhtmlNoNamespace.p) { @@ -950,13 +1059,18 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, // new XElement(W.r, // new XElement(W.t, element.Value))); //} - if (element.Name == XhtmlNoNamespace.span && (string)element.Attribute(XhtmlNoNamespace.id) == "layoutsData") + if ( + element.Name == XhtmlNoNamespace.span + && (string)element.Attribute(XhtmlNoNamespace.id) == "layoutsData" + ) return null; /****************************************** End SharePoint Specific ********************************************/ if (element.Name == XhtmlNoNamespace.span) { - var spanReplacement = element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); + var spanReplacement = element + .Nodes() + .Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); var dummyElement = new XElement("dummy", spanReplacement); var firstChild = dummyElement.Elements().FirstOrDefault(); XElement run = null; @@ -975,7 +1089,13 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, var styleDefPart = wDoc.MainDocumentPart.StyleDefinitionsPart; if (styleDefPart != null) { - rFontsGlobal = styleDefPart.GetXDocument().Root.Elements(W.docDefaults).Elements(W.rPrDefault).Elements(W.rPr).Elements(W.rFonts).FirstOrDefault(); + rFontsGlobal = styleDefPart + .GetXDocument() + .Root.Elements(W.docDefaults) + .Elements(W.rPrDefault) + .Elements(W.rPr) + .Elements(W.rFonts) + .FirstOrDefault(); } var rFontsNew = FontMerge(rFontsLocal, rFontsGlobal); var rPr = run.Element(W.rPr); @@ -1008,61 +1128,82 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, if (element.Name == XhtmlNoNamespace.table) { - var wmlTable = new XElement(W.tbl, + var wmlTable = new XElement( + W.tbl, GetTableProperties(element), GetTableGrid(element, settings), - element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace))); + element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)) + ); return wmlTable; } if (element.Name == XhtmlNoNamespace.tbody) - return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); + return element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)); if (element.Name == XhtmlNoNamespace.td) { - var tdText = element.DescendantNodes().OfType().Select(t => t.Value).StringConcatenate().Trim(); - var hasOtherThanSpansAndParas = element.Descendants().Any(d => d.Name != XhtmlNoNamespace.span && d.Name != XhtmlNoNamespace.p); + var tdText = element + .DescendantNodes() + .OfType() + .Select(t => t.Value) + .StringConcatenate() + .Trim(); + var hasOtherThanSpansAndParas = element + .Descendants() + .Any(d => d.Name != XhtmlNoNamespace.span && d.Name != XhtmlNoNamespace.p); if (tdText != "" || hasOtherThanSpansAndParas) { - var newElementRaw = new XElement("dummy", element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace))); - var newElements = new XElement("dummy", + var newElementRaw = new XElement( + "dummy", + element + .Nodes() + .Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)) + ); + var newElements = new XElement( + "dummy", newElementRaw - .Elements() - .Select(e => - { - if (e.Name == W.hyperlink || e.Name == W.r) - return new XElement(W.p, e); - return e; - })); - - return new XElement(W.tc, - GetCellProperties(element), - newElements.Elements()); + .Elements() + .Select(e => + { + if (e.Name == W.hyperlink || e.Name == W.r) + return new XElement(W.p, e); + return e; + }) + ); + + return new XElement(W.tc, GetCellProperties(element), newElements.Elements()); } else { - var p = new XElement(W.p, + var p = new XElement( + W.p, GetParagraphProperties(element, null, settings), - new XElement(W.r, - GetRunProperties(element, settings), - new XElement(W.t, ""))); - return new XElement(W.tc, - GetCellProperties(element), p); + new XElement(W.r, GetRunProperties(element, settings), new XElement(W.t, "")) + ); + return new XElement(W.tc, GetCellProperties(element), p); } } if (element.Name == XhtmlNoNamespace.th) { - return new XElement(W.tc, + return new XElement( + W.tc, GetCellHeaderProperties(element), - element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace))); + element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)) + ); } if (element.Name == XhtmlNoNamespace.tr) { - return new XElement(W.tr, + return new XElement( + W.tr, GetTableRowProperties(element), - element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace))); + element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)) + ); } if (element.Name == XhtmlNoNamespace.u) @@ -1074,16 +1215,19 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, if (element.Name == XhtmlNoNamespace.br) if (nextExpected == NextExpected.Paragraph) { - return new XElement(W.p, - new XElement(W.r, - new XElement(W.t))); + return new XElement(W.p, new XElement(W.r, new XElement(W.t))); } else { return new XElement(W.r, new XElement(W.br)); } - if (element.Name == XhtmlNoNamespace.tt || element.Name == XhtmlNoNamespace.code || element.Name == XhtmlNoNamespace.kbd || element.Name == XhtmlNoNamespace.samp) + if ( + element.Name == XhtmlNoNamespace.tt + || element.Name == XhtmlNoNamespace.code + || element.Name == XhtmlNoNamespace.kbd + || element.Name == XhtmlNoNamespace.samp + ) return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)); if (element.Name == XhtmlNoNamespace.pre) @@ -1097,7 +1241,6 @@ private static object Transform(XNode node, HtmlToWmlConverterSettings settings, return GenerateNextExpected(node, settings, wDoc, null, nextExpected, preserveWhiteSpace); return null; - } private static XElement FontMerge(XElement higherPriorityFont, XElement lowerPriorityFont) @@ -1109,21 +1252,28 @@ private static XElement FontMerge(XElement higherPriorityFont, XElement lowerPri if (higherPriorityFont == null && lowerPriorityFont == null) return null; - var rFonts = new XElement(W.rFonts, - (higherPriorityFont.Attribute(W.ascii) != null || higherPriorityFont.Attribute(W.asciiTheme) != null) ? - new[] { higherPriorityFont.Attribute(W.ascii), higherPriorityFont.Attribute(W.asciiTheme) } : - new[] { lowerPriorityFont.Attribute(W.ascii), lowerPriorityFont.Attribute(W.asciiTheme) }, - (higherPriorityFont.Attribute(W.hAnsi) != null || higherPriorityFont.Attribute(W.hAnsiTheme) != null) ? - new[] { higherPriorityFont.Attribute(W.hAnsi), higherPriorityFont.Attribute(W.hAnsiTheme) } : - new[] { lowerPriorityFont.Attribute(W.hAnsi), lowerPriorityFont.Attribute(W.hAnsiTheme) }, - (higherPriorityFont.Attribute(W.eastAsia) != null || higherPriorityFont.Attribute(W.eastAsiaTheme) != null) ? - new[] { higherPriorityFont.Attribute(W.eastAsia), higherPriorityFont.Attribute(W.eastAsiaTheme) } : - new[] { lowerPriorityFont.Attribute(W.eastAsia), lowerPriorityFont.Attribute(W.eastAsiaTheme) }, - (higherPriorityFont.Attribute(W.cs) != null || higherPriorityFont.Attribute(W.cstheme) != null) ? - new[] { higherPriorityFont.Attribute(W.cs), higherPriorityFont.Attribute(W.cstheme) } : - new[] { lowerPriorityFont.Attribute(W.cs), lowerPriorityFont.Attribute(W.cstheme) }, - (higherPriorityFont.Attribute(W.hint) != null ? higherPriorityFont.Attribute(W.hint) : - lowerPriorityFont.Attribute(W.hint)) + var rFonts = new XElement( + W.rFonts, + (higherPriorityFont.Attribute(W.ascii) != null || higherPriorityFont.Attribute(W.asciiTheme) != null) + ? new[] { higherPriorityFont.Attribute(W.ascii), higherPriorityFont.Attribute(W.asciiTheme) } + : new[] { lowerPriorityFont.Attribute(W.ascii), lowerPriorityFont.Attribute(W.asciiTheme) }, + (higherPriorityFont.Attribute(W.hAnsi) != null || higherPriorityFont.Attribute(W.hAnsiTheme) != null) + ? new[] { higherPriorityFont.Attribute(W.hAnsi), higherPriorityFont.Attribute(W.hAnsiTheme) } + : new[] { lowerPriorityFont.Attribute(W.hAnsi), lowerPriorityFont.Attribute(W.hAnsiTheme) }, + ( + higherPriorityFont.Attribute(W.eastAsia) != null + || higherPriorityFont.Attribute(W.eastAsiaTheme) != null + ) + ? new[] { higherPriorityFont.Attribute(W.eastAsia), higherPriorityFont.Attribute(W.eastAsiaTheme) } + : new[] { lowerPriorityFont.Attribute(W.eastAsia), lowerPriorityFont.Attribute(W.eastAsiaTheme) }, + (higherPriorityFont.Attribute(W.cs) != null || higherPriorityFont.Attribute(W.cstheme) != null) + ? new[] { higherPriorityFont.Attribute(W.cs), higherPriorityFont.Attribute(W.cstheme) } + : new[] { lowerPriorityFont.Attribute(W.cs), lowerPriorityFont.Attribute(W.cstheme) }, + ( + higherPriorityFont.Attribute(W.hint) != null + ? higherPriorityFont.Attribute(W.hint) + : lowerPriorityFont.Attribute(W.hint) + ) ); return rFonts; @@ -1140,7 +1290,7 @@ public enum FontType Ascii, HAnsi, EastAsia, - CS + CS, }; public class CharStyleAttributes @@ -1194,12 +1344,15 @@ public CharStyleAttributes(XElement pPr, XElement rPr) var csel = this.Properties[W.cs]; var cs = csel != null && (csel.Attribute(W.val) == null || csel.Attribute(W.val).ToBoolean() == true); var rtlel = this.Properties[W.rtl]; - var rtl = rtlel != null && (rtlel.Attribute(W.val) == null || rtlel.Attribute(W.val).ToBoolean() == true); + var rtl = + rtlel != null && (rtlel.Attribute(W.val) == null || rtlel.Attribute(W.val).ToBoolean() == true); var bidi = false; if (pPr != null) { var bidiel = pPr.Element(W.bidi); - bidi = bidiel != null && (bidiel.Attribute(W.val) == null || bidiel.Attribute(W.val).ToBoolean() == true); + bidi = + bidiel != null + && (bidiel.Attribute(W.val) == null || bidiel.Attribute(W.val).ToBoolean() == true); } Rtl = cs || rtl || bidi; var lang = rPr.Element(W.lang); @@ -1216,7 +1369,8 @@ private static XElement GetXmlProperty(XElement rPr, XName propertyName) return rPr.Element(propertyName); } - private static readonly XName[] TogglePropertyNames = new[] { + private static readonly XName[] TogglePropertyNames = new[] + { W.b, W.bCs, W.caps, @@ -1228,18 +1382,10 @@ private static XElement GetXmlProperty(XElement rPr, XName propertyName) W.shadow, W.smallCaps, W.strike, - W.vanish - }; - - private static readonly XName[] PropertyNames = new[] { - W.cs, - W.rtl, - W.u, - W.color, - W.highlight, - W.shd + W.vanish, }; + private static readonly XName[] PropertyNames = new[] { W.cs, W.rtl, W.u, W.color, W.highlight, W.shd }; } public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttributes csa) @@ -1261,8 +1407,7 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut // If the eastAsia (or eastAsiaTheme if defined) attribute’s value is “Times New Roman” and the ascii (or asciiTheme if defined) // and hAnsi (or hAnsiTheme if defined) attributes are equal, then the ascii (or asciiTheme if defined) font is used. - if (csa.EastAsiaFont == "Times New Roman" && - csa.AsciiFont == csa.HAnsiFont) + if (csa.EastAsiaFont == "Times New Roman" && csa.AsciiFont == csa.HAnsiFont) { return FontType.Ascii; } @@ -1272,30 +1417,34 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut { if (csa.Hint == "eastAsia") { - if (ch == 0xA1 || - ch == 0xA4 || - ch == 0xA7 || - ch == 0xA8 || - ch == 0xAA || - ch == 0xAD || - ch == 0xAF || - (ch >= 0xB0 && ch <= 0xB4) || - (ch >= 0xB6 && ch <= 0xBA) || - (ch >= 0xBC && ch <= 0xBF) || - ch == 0xD7 || - ch == 0xF7) + if ( + ch == 0xA1 + || ch == 0xA4 + || ch == 0xA7 + || ch == 0xA8 + || ch == 0xAA + || ch == 0xAD + || ch == 0xAF + || (ch >= 0xB0 && ch <= 0xB4) + || (ch >= 0xB6 && ch <= 0xBA) + || (ch >= 0xBC && ch <= 0xBF) + || ch == 0xD7 + || ch == 0xF7 + ) { return FontType.EastAsia; } if (csa.EastAsiaLang is "zh-hant" or "zh-hans") { - if (ch == 0xE0 || - ch == 0xE1 || - (ch >= 0xE8 && ch <= 0xEA) || - (ch >= 0xEC && ch <= 0xED) || - (ch >= 0xF2 && ch <= 0xF3) || - (ch >= 0xF9 && ch <= 0xFA) || - ch == 0xFC) + if ( + ch == 0xE0 + || ch == 0xE1 + || (ch >= 0xE8 && ch <= 0xEA) + || (ch >= 0xEC && ch <= 0xED) + || (ch >= 0xF2 && ch <= 0xF3) + || (ch >= 0xF9 && ch <= 0xFA) + || ch == 0xFC + ) { return FontType.EastAsia; } @@ -1309,8 +1458,9 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut { if (csa.Hint == "eastAsia") { - if (csa.EastAsiaLang is "zh-hant" or "zh-hans" - /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) + if ( + csa.EastAsiaLang is "zh-hant" or "zh-hans" + /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) { return FontType.EastAsia; } @@ -1323,8 +1473,9 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut { if (csa.Hint == "eastAsia") { - if (csa.EastAsiaLang is "zh-hant" or "zh-hans" - /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) + if ( + csa.EastAsiaLang is "zh-hant" or "zh-hans" + /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) { return FontType.EastAsia; } @@ -1337,8 +1488,9 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut { if (csa.Hint == "eastAsia") { - if (csa.EastAsiaLang is "zh-hant" or "zh-hans" - /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) + if ( + csa.EastAsiaLang is "zh-hant" or "zh-hans" + /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */) { return FontType.EastAsia; } @@ -1425,8 +1577,7 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut // Unicode Block: Latin Extended Additional if (ch >= 0x1E00 && ch <= 0x1EFF) { - if (csa.Hint == "eastAsia" && - csa.EastAsiaLang is "zh-hant" or "zh-hans") + if (csa.Hint == "eastAsia" && csa.EastAsiaLang is "zh-hant" or "zh-hans") { return FontType.EastAsia; } @@ -1782,7 +1933,8 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut return FontType.HAnsi; } - private static readonly HashSet WeakAndNeutralDirectionalCharacters = new HashSet() { + private static readonly HashSet WeakAndNeutralDirectionalCharacters = new HashSet() + { '0', '1', '2', @@ -1804,13 +1956,10 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut '\n', ' ', '\x00A0', // non breaking space - '\x00B0', // degree sign '\x066B', // arabic decimal separator '\x066C', // arabic thousands separator - '\x0627', // arabic pipe - '\x20A0', // start currency symbols '\x20A1', '\x20A2', @@ -1858,8 +2007,7 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut '\x20CC', '\x20CD', '\x20CE', - '\x20CF', // end currency symbols - + '\x20CF', // end currency symbols '\x0660', // "Arabic" Indic Numeral Forms Iraq and West '\x0661', '\x0662', @@ -1870,7 +2018,6 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut '\x0667', '\x0668', '\x0669', - '\x06F0', // "Arabic" Indic Numberal Forms Iran and East '\x06F1', '\x06F2', @@ -1883,7 +2030,12 @@ public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttribut '\x06F9', }; - private static void AdjustFontAttributes(WordprocessingDocument wDoc, XElement paraOrRun, XElement pPr, XElement rPr) + private static void AdjustFontAttributes( + WordprocessingDocument wDoc, + XElement paraOrRun, + XElement pPr, + XElement rPr + ) { XDocument themeXDoc = null; if (wDoc.MainDocumentPart.ThemePart != null) @@ -2099,7 +2251,8 @@ old code private static decimal? GetFontSize(string languageType, XElement rPr) { - if (rPr == null) return null; + if (rPr == null) + return null; return languageType == "bidi" ? (decimal?)rPr.Elements(W.szCs).Attributes(W.val).FirstOrDefault() : (decimal?)rPr.Elements(W.sz).Attributes(W.val).FirstOrDefault(); @@ -2112,17 +2265,25 @@ private static int GetNextRectId() return NextRectId++; } - private static object GenerateNextExpected(XNode node, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, - string styleName, NextExpected nextExpected, bool preserveWhiteSpace) + private static object GenerateNextExpected( + XNode node, + HtmlToWmlConverterSettings settings, + WordprocessingDocument wDoc, + string styleName, + NextExpected nextExpected, + bool preserveWhiteSpace + ) { if (nextExpected == NextExpected.Paragraph) { var element = node as XElement; if (element != null) { - return new XElement(W.p, + return new XElement( + W.p, GetParagraphProperties(element, styleName, settings), - element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace))); + element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace)) + ); } else { @@ -2130,13 +2291,15 @@ private static object GenerateNextExpected(XNode node, HtmlToWmlConverterSetting if (xTextNode != null) { var textNodeString = GetDisplayText(xTextNode, preserveWhiteSpace); - var p = new XElement(W.p, + var p = new XElement( + W.p, GetParagraphProperties(node.Parent, null, settings), - new XElement(W.r, + new XElement( + W.r, GetRunProperties((XText)node, settings), - new XElement(W.t, - GetXmlSpaceAttribute(textNodeString), - textNodeString))); + new XElement(W.t, GetXmlSpaceAttribute(textNodeString), textNodeString) + ) + ); return p; } return null; @@ -2153,17 +2316,21 @@ private static object GenerateNextExpected(XNode node, HtmlToWmlConverterSetting { var textNodeString = GetDisplayText((XText)node, preserveWhiteSpace); var rPr = GetRunProperties((XText)node, settings); - var r = new XElement(W.r, + var r = new XElement( + W.r, rPr, - new XElement(W.t, - GetXmlSpaceAttribute(textNodeString), - textNodeString)); + new XElement(W.t, GetXmlSpaceAttribute(textNodeString), textNodeString) + ); return r; } } } - private static XElement TransformImageToWml(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc) + private static XElement TransformImageToWml( + XElement element, + HtmlToWmlConverterSettings settings, + WordprocessingDocument wDoc + ) { var srcAttribute = (string)element.Attribute(XhtmlNoNamespace.src); byte[] ba = null; @@ -2211,10 +2378,7 @@ private static XElement TransformImageToWml(XElement element, HtmlToWmlConverter var pid = wDoc.Annotation(); if (pid == null) { - pid = new PictureId - { - Id = 1, - }; + pid = new PictureId { Id = 1 }; wDoc.AddAnnotation(pid); } var pictureId = pid.Id; @@ -2225,45 +2389,70 @@ private static XElement TransformImageToWml(XElement element, HtmlToWmlConverter var floatValue = element.GetProp("float").ToString(); if (floatValue == "none") { - var run = new XElement(W.r, + var run = new XElement( + W.r, GetRunPropertiesForImage(), - new XElement(W.drawing, - GetImageAsInline(element, settings, wDoc, bmp, rId, pictureId, pictureDescription))); + new XElement( + W.drawing, + GetImageAsInline(element, settings, wDoc, bmp, rId, pictureId, pictureDescription) + ) + ); return run; } if (floatValue is "left" or "right") { - var run = new XElement(W.r, + var run = new XElement( + W.r, GetRunPropertiesForImage(), - new XElement(W.drawing, - GetImageAsAnchor(element, settings, wDoc, bmp, rId, floatValue, pictureId, pictureDescription))); + new XElement( + W.drawing, + GetImageAsAnchor(element, settings, wDoc, bmp, rId, floatValue, pictureId, pictureDescription) + ) + ); return run; } return null; } - private static XElement GetImageAsInline(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, Image bmp, - string rId, int pictureId, string pictureDescription) + private static XElement GetImageAsInline( + XElement element, + HtmlToWmlConverterSettings settings, + WordprocessingDocument wDoc, + Image bmp, + string rId, + int pictureId, + string pictureDescription + ) { - var inline = new XElement(WP.inline, // 20.4.2.8 + var inline = new XElement( + WP.inline, // 20.4.2.8 new XAttribute(XNamespace.Xmlns + "wp", WP.wp.NamespaceName), - new XAttribute(NoNamespace.distT, 0), // distance from top of image to text, in EMUs, no effect if the parent is inline - new XAttribute(NoNamespace.distB, 0), // bottom - new XAttribute(NoNamespace.distL, 0), // left - new XAttribute(NoNamespace.distR, 0), // right + new XAttribute(NoNamespace.distT, 0), // distance from top of image to text, in EMUs, no effect if the parent is inline + new XAttribute(NoNamespace.distB, 0), // bottom + new XAttribute(NoNamespace.distL, 0), // left + new XAttribute(NoNamespace.distR, 0), // right GetImageExtent(element, bmp), GetEffectExtent(), GetDocPr(element, pictureId, pictureDescription), GetCNvGraphicFramePr(), - GetGraphicForImage(element, rId, bmp, pictureId, pictureDescription)); + GetGraphicForImage(element, rId, bmp, pictureId, pictureDescription) + ); return inline; } - private static XElement GetImageAsAnchor(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, Image bmp, - string rId, string floatValue, int pictureId, string pictureDescription) + private static XElement GetImageAsAnchor( + XElement element, + HtmlToWmlConverterSettings settings, + WordprocessingDocument wDoc, + Image bmp, + string rId, + string floatValue, + int pictureId, + string pictureDescription + ) { Emu minDistFromEdge = (long)(0.125 * Emu.s_EmusPerInch); - long relHeight = 251658240; // z-order + long relHeight = 251658240; // z-order var marginTopProp = element.GetProp("margin-top"); var marginLeftProp = element.GetProp("margin-left"); @@ -2314,12 +2503,13 @@ private static XElement GetImageAsAnchor(XElement element, HtmlToWmlConverterSet if (parentMarginTop.IsNotAuto) relativeFromParagraph += (Emu)parentMarginTop; - var anchor = new XElement(WP.anchor, + var anchor = new XElement( + WP.anchor, new XAttribute(XNamespace.Xmlns + "wp", WP.wp.NamespaceName), - new XAttribute(NoNamespace.distT, (long)marginTopInEmus), // distance from top of image to text, in EMUs, no effect if the parent is inline - new XAttribute(NoNamespace.distB, (long)marginBottomInEmus), // bottom - new XAttribute(NoNamespace.distL, (long)marginLeftInEmus), // left - new XAttribute(NoNamespace.distR, (long)marginRightInEmus), // right + new XAttribute(NoNamespace.distT, (long)marginTopInEmus), // distance from top of image to text, in EMUs, no effect if the parent is inline + new XAttribute(NoNamespace.distB, (long)marginBottomInEmus), // bottom + new XAttribute(NoNamespace.distL, (long)marginLeftInEmus), // left + new XAttribute(NoNamespace.distR, (long)marginRightInEmus), // right new XAttribute(NoNamespace.simplePos, 0), new XAttribute(NoNamespace.relativeHeight, relHeight), new XAttribute(NoNamespace.behindDoc, 0), @@ -2327,20 +2517,32 @@ private static XElement GetImageAsAnchor(XElement element, HtmlToWmlConverterSet new XAttribute(NoNamespace.layoutInCell, 1), new XAttribute(NoNamespace.allowOverlap, 1), new XElement(WP.simplePos, new XAttribute(NoNamespace.x, 0), new XAttribute(NoNamespace.y, 0)), - new XElement(WP.positionH, new XAttribute(NoNamespace.relativeFrom, "column"), - new XElement(WP.posOffset, (long)relativeFromColumn)), - new XElement(WP.positionV, new XAttribute(NoNamespace.relativeFrom, "paragraph"), - new XElement(WP.posOffset, (long)relativeFromParagraph)), + new XElement( + WP.positionH, + new XAttribute(NoNamespace.relativeFrom, "column"), + new XElement(WP.posOffset, (long)relativeFromColumn) + ), + new XElement( + WP.positionV, + new XAttribute(NoNamespace.relativeFrom, "paragraph"), + new XElement(WP.posOffset, (long)relativeFromParagraph) + ), GetImageExtent(element, bmp), GetEffectExtent(), new XElement(WP.wrapSquare, new XAttribute(NoNamespace.wrapText, "bothSides")), GetDocPr(element, pictureId, pictureDescription), GetCNvGraphicFramePr(), GetGraphicForImage(element, rId, bmp, pictureId, pictureDescription), - new XElement(WP14.sizeRelH, new XAttribute(NoNamespace.relativeFrom, "page"), - new XElement(WP14.pctWidth, 0)), - new XElement(WP14.sizeRelV, new XAttribute(NoNamespace.relativeFrom, "page"), - new XElement(WP14.pctHeight, 0)) + new XElement( + WP14.sizeRelH, + new XAttribute(NoNamespace.relativeFrom, "page"), + new XElement(WP14.pctWidth, 0) + ), + new XElement( + WP14.sizeRelV, + new XAttribute(NoNamespace.relativeFrom, "page"), + new XElement(WP14.pctHeight, 0) + ) ); return anchor; } @@ -2436,8 +2638,7 @@ private static XElement GetParagraphPropertiesForImage() private static XElement GetRunPropertiesForImage() { - return new XElement(W.rPr, - new XElement(W.noProof)); + return new XElement(W.rPr, new XElement(W.noProof)); } private static SizeEmu GetImageSizeInEmus(XElement img, Image bmp) @@ -2476,74 +2677,116 @@ private static SizeEmu GetImageSizeInEmus(XElement img, Image bmp) private static XElement GetImageExtent(XElement img, Image bmp) { var szEmu = GetImageSizeInEmus(img, bmp); - return new XElement(WP.extent, - new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), // in EMUs - new XAttribute(NoNamespace.cy, (long)szEmu.m_Height)); // in EMUs + return new XElement( + WP.extent, + new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), // in EMUs + new XAttribute(NoNamespace.cy, (long)szEmu.m_Height) + ); // in EMUs } private static XElement GetEffectExtent() { - return new XElement(WP.effectExtent, + return new XElement( + WP.effectExtent, new XAttribute(NoNamespace.l, 0), new XAttribute(NoNamespace.t, 0), new XAttribute(NoNamespace.r, 0), - new XAttribute(NoNamespace.b, 0)); + new XAttribute(NoNamespace.b, 0) + ); } private static XElement GetDocPr(XElement element, int pictureId, string pictureDescription) { - return new XElement(WP.docPr, + return new XElement( + WP.docPr, new XAttribute(NoNamespace.id, pictureId), new XAttribute(NoNamespace.name, pictureDescription), - new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src))); + new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src)) + ); } private static XElement GetCNvGraphicFramePr() { - return new XElement(WP.cNvGraphicFramePr, - new XElement(A.graphicFrameLocks, + return new XElement( + WP.cNvGraphicFramePr, + new XElement( + A.graphicFrameLocks, new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName), - new XAttribute(NoNamespace.noChangeAspect, 1))); + new XAttribute(NoNamespace.noChangeAspect, 1) + ) + ); } - private static XElement GetGraphicForImage(XElement element, string rId, Image bmp, int pictureId, string pictureDescription) + private static XElement GetGraphicForImage( + XElement element, + string rId, + Image bmp, + int pictureId, + string pictureDescription + ) { var szEmu = GetImageSizeInEmus(element, bmp); - var graphic = new XElement(A.graphic, + var graphic = new XElement( + A.graphic, new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName), - new XElement(A.graphicData, + new XElement( + A.graphicData, new XAttribute(NoNamespace.uri, Pic.pic.NamespaceName), - new XElement(Pic._pic, + new XElement( + Pic._pic, new XAttribute(XNamespace.Xmlns + "pic", Pic.pic.NamespaceName), - new XElement(Pic.nvPicPr, - new XElement(Pic.cNvPr, + new XElement( + Pic.nvPicPr, + new XElement( + Pic.cNvPr, new XAttribute(NoNamespace.id, pictureId), new XAttribute(NoNamespace.name, pictureDescription), - new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src))), - new XElement(Pic.cNvPicPr, - new XElement(A.picLocks, + new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src)) + ), + new XElement( + Pic.cNvPicPr, + new XElement( + A.picLocks, new XAttribute(NoNamespace.noChangeAspect, 1), - new XAttribute(NoNamespace.noChangeArrowheads, 1)))), - new XElement(Pic.blipFill, - new XElement(A.blip, + new XAttribute(NoNamespace.noChangeArrowheads, 1) + ) + ) + ), + new XElement( + Pic.blipFill, + new XElement( + A.blip, new XAttribute(R.embed, rId), - new XElement(A.extLst, - new XElement(A.ext, + new XElement( + A.extLst, + new XElement( + A.ext, new XAttribute(NoNamespace.uri, "{28A0092B-C50C-407E-A947-70E740481C1C}"), - new XElement(A14.useLocalDpi, - new XAttribute(NoNamespace.val, "0"))))), - new XElement(A.stretch, - new XElement(A.fillRect))), - new XElement(Pic.spPr, + new XElement(A14.useLocalDpi, new XAttribute(NoNamespace.val, "0")) + ) + ) + ), + new XElement(A.stretch, new XElement(A.fillRect)) + ), + new XElement( + Pic.spPr, new XAttribute(NoNamespace.bwMode, "auto"), - new XElement(A.xfrm, + new XElement( + A.xfrm, new XElement(A.off, new XAttribute(NoNamespace.x, 0), new XAttribute(NoNamespace.y, 0)), - new XElement(A.ext, new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), new XAttribute(NoNamespace.cy, (long)szEmu.m_Height))), - new XElement(A.prstGeom, new XAttribute(NoNamespace.prst, "rect"), - new XElement(A.avLst)), + new XElement( + A.ext, + new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), + new XAttribute(NoNamespace.cy, (long)szEmu.m_Height) + ) + ), + new XElement(A.prstGeom, new XAttribute(NoNamespace.prst, "rect"), new XElement(A.avLst)), new XElement(A.noFill), - new XElement(A.ln, - new XElement(A.noFill)))))); + new XElement(A.ln, new XElement(A.noFill)) + ) + ) + ) + ); return graphic; } @@ -2587,7 +2830,11 @@ private static XElement GetGraphicForImage(XElement element, string rId, Image b #endif - private static XElement GetParagraphProperties(XElement blockLevelElement, string styleName, HtmlToWmlConverterSettings settings) + private static XElement GetParagraphProperties( + XElement blockLevelElement, + string styleName, + HtmlToWmlConverterSettings settings + ) { var paragraphMarkRunProperties = GetRunProperties(blockLevelElement, settings); var backgroundProperty = GetBackgroundProperty(blockLevelElement); @@ -2602,7 +2849,8 @@ private static XElement GetParagraphProperties(XElement blockLevelElement, strin if (direction == "rtl") bidi = new XElement(W.bidi); - var pPr = new XElement(W.pPr, + var pPr = new XElement( + W.pPr, pStyle, numPr, pBdr, @@ -2658,7 +2906,9 @@ private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConv } XElement listElement = null; NumberedItemAnnotation numberedItemAnnotation = null; - listElement = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); + listElement = paragraph + .Ancestors() + .FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); if (listElement != null) { numberedItemAnnotation = listElement.Annotation(); @@ -2685,15 +2935,19 @@ private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConv if (leftIndent > 0 || rightIndent > 0 || firstLine != 0) { if (firstLine < 0) - ind = new XElement(W.ind, + ind = new XElement( + W.ind, leftIndent != 0 ? new XAttribute(W.left, (long)leftIndent) : null, rightIndent != 0 ? new XAttribute(W.right, (long)rightIndent) : null, - firstLine != 0 ? new XAttribute(W.hanging, -firstLine) : null); + firstLine != 0 ? new XAttribute(W.hanging, -firstLine) : null + ); else - ind = new XElement(W.ind, + ind = new XElement( + W.ind, leftIndent != 0 ? new XAttribute(W.left, (long)leftIndent) : null, rightIndent != 0 ? new XAttribute(W.right, (long)rightIndent) : null, - firstLine != 0 ? new XAttribute(W.firstLine, (long)firstLine) : null); + firstLine != 0 ? new XAttribute(W.firstLine, (long)firstLine) : null + ); } /*****************************************************************************************/ @@ -2706,14 +2960,20 @@ private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConv long? before = null; long? after = null; - if (paragraph.Name == XhtmlNoNamespace.td || paragraph.Name == XhtmlNoNamespace.th || paragraph.Name == XhtmlNoNamespace.caption) + if ( + paragraph.Name == XhtmlNoNamespace.td + || paragraph.Name == XhtmlNoNamespace.th + || paragraph.Name == XhtmlNoNamespace.caption + ) { line = (long)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.line); lineRule = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.lineRule); before = (long?)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.before); - beforeAutospacing = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.beforeAutospacing); + beforeAutospacing = (string) + settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.beforeAutospacing); after = (long?)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.after); - afterAutospacing = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.afterAutospacing); + afterAutospacing = (string) + settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.afterAutospacing); } // todo should check based on display property @@ -2740,13 +3000,15 @@ private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConv lineRule = "atLeast"; } - var spacing = new XElement(W.spacing, + var spacing = new XElement( + W.spacing, before != null ? new XAttribute(W.before, before) : null, beforeAutospacing != null ? new XAttribute(W.beforeAutospacing, beforeAutospacing) : null, after != null ? new XAttribute(W.after, after) : null, afterAutospacing != null ? new XAttribute(W.afterAutospacing, afterAutospacing) : null, new XAttribute(W.line, line), - new XAttribute(W.lineRule, lineRule)); + new XAttribute(W.lineRule, lineRule) + ); /*****************************************************************************************/ // contextualSpacing @@ -2755,16 +3017,22 @@ private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConv if (paragraph.Name == XhtmlNoNamespace.li) { NumberedItemAnnotation thisNumberedItemAnnotation = null; - var listElement2 = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); + var listElement2 = paragraph + .Ancestors() + .FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); if (listElement2 != null) { thisNumberedItemAnnotation = listElement2.Annotation(); var next = paragraph.ElementsAfterSelf().FirstOrDefault(); if (next != null && next.Name == XhtmlNoNamespace.li) { - var nextListElement = next.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); + var nextListElement = next.Ancestors() + .FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); var nextNumberedItemAnnotation = nextListElement.Annotation(); - if (nextNumberedItemAnnotation != null && thisNumberedItemAnnotation.numId == nextNumberedItemAnnotation.numId) + if ( + nextNumberedItemAnnotation != null + && thisNumberedItemAnnotation.numId == nextNumberedItemAnnotation.numId + ) contextualSpacing = new XElement(W.contextualSpacing); } } @@ -2818,29 +3086,33 @@ private static XElement GetRunProperties(XElement element, HtmlToWmlConverterSet XElement shd = null; if (backgroundColorString != "transparent") - shd = new XElement(W.shd, new XAttribute(W.val, "clear"), + shd = new XElement( + W.shd, + new XAttribute(W.val, "clear"), new XAttribute(W.color, "auto"), - new XAttribute(W.fill, backgroundColorString)); + new XAttribute(W.fill, backgroundColorString) + ); XElement subSuper = null; if (subAncestor) subSuper = new XElement(W.vertAlign, new XAttribute(W.val, "subscript")); - else - if (supAncestor) - subSuper = new XElement(W.vertAlign, new XAttribute(W.val, "superscript")); + else if (supAncestor) + subSuper = new XElement(W.vertAlign, new XAttribute(W.val, "superscript")); XElement rFonts = null; if (fontFamilyString != null) { - rFonts = new XElement(W.rFonts, + rFonts = new XElement( + W.rFonts, fontFamilyString != settings.MinorLatinFont ? new XAttribute(W.ascii, fontFamilyString) : null, fontFamilyString != settings.MajorLatinFont ? new XAttribute(W.hAnsi, fontFamilyString) : null, - new XAttribute(W.cs, fontFamilyString)); + new XAttribute(W.cs, fontFamilyString) + ); } // todo I think this puts a color on every element. - var color = colorPropertyString != null ? - new XElement(W.color, new XAttribute(W.val, colorPropertyString)) : null; + var color = + colorPropertyString != null ? new XElement(W.color, new XAttribute(W.val, colorPropertyString)) : null; XElement sz = null; XElement szCs = null; @@ -2856,7 +3128,11 @@ private static XElement GetRunProperties(XElement element, HtmlToWmlConverterSet XElement bold = null; XElement boldCs = null; - if (bAncestor || strongAncestor || fontWeightString is "bold" or "bolder" or "600" or "700" or "800" or "900") + if ( + bAncestor + || strongAncestor + || fontWeightString is "bold" or "bolder" or "600" or "700" or "800" or "900" + ) { bold = new XElement(W.b); boldCs = new XElement(W.bCs); @@ -2876,19 +3152,18 @@ private static XElement GetRunProperties(XElement element, HtmlToWmlConverterSet XElement rStyle = null; if (element.Name == XhtmlNoNamespace.a) - rStyle = new XElement(W.rStyle, - new XAttribute(W.val, "Hyperlink")); + rStyle = new XElement(W.rStyle, new XAttribute(W.val, "Hyperlink")); XElement spacing = null; if (letterSpacingProperty.IsNotNormal) - spacing = new XElement(W.spacing, - new XAttribute(W.val, (long)(Twip)letterSpacingProperty)); + spacing = new XElement(W.spacing, new XAttribute(W.val, (long)(Twip)letterSpacingProperty)); XElement rtl = null; if (dirAttributeString == "rtl" || directionString == "rtl") rtl = new XElement(W.rtl); - var runProps = new XElement(W.rPr, + var runProps = new XElement( + W.rPr, rStyle, rFonts, bold, @@ -2903,7 +3178,8 @@ private static XElement GetRunProperties(XElement element, HtmlToWmlConverterSet underline, shd, subSuper, - rtl); + rtl + ); if (runProps.Elements().Any()) return runProps; @@ -2927,13 +3203,14 @@ private static string GetDisplayText(XText node, bool preserveWhiteSpace) else groupedCharacters = node.Value.GroupAdjacent(c => c is ' ' or '\r' or '\n'); - var newString = groupedCharacters.Select(g => - { - if (g.Key) - return " "; - var x = g.Select(c => c.ToString()).StringConcatenate(); - return x; - }) + var newString = groupedCharacters + .Select(g => + { + if (g.Key) + return " "; + var x = g.Select(c => c.ToString()).StringConcatenate(); + return x; + }) .StringConcatenate(); if (!preserveWhiteSpace) { @@ -2947,7 +3224,7 @@ private static string GetDisplayText(XText node, bool preserveWhiteSpace) "uppercase" => newString.ToUpper(), "lowercase" => newString.ToLower(), "capitalize" => newString.Substring(0, 1).ToUpper() + newString.Substring(1).ToLower(), - _ => newString + _ => newString, }; return newString; } @@ -2956,16 +3233,20 @@ private static XElement GetNumberingProperties(XElement paragraph, HtmlToWmlConv { // Numbering properties ****************************************************** NumberedItemAnnotation numberedItemAnnotation = null; - var listElement = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); + var listElement = paragraph + .Ancestors() + .FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul); if (listElement != null) { numberedItemAnnotation = listElement.Annotation(); } XElement numPr = null; if (paragraph.Name == XhtmlNoNamespace.li) - numPr = new XElement(W.numPr, + numPr = new XElement( + W.numPr, new XElement(W.ilvl, new XAttribute(W.val, numberedItemAnnotation.ilvl)), - new XElement(W.numId, new XAttribute(W.val, numberedItemAnnotation.numId))); + new XElement(W.numId, new XAttribute(W.val, numberedItemAnnotation.numId)) + ); return numPr; } @@ -2985,7 +3266,7 @@ private static XElement GetJustification(XElement blockLevelElement, HtmlToWmlCo "center" => "center", "right" => "right", "justify" => "both", - _ => null + _ => null, }; var direction = GetDirection(blockLevelElement); if (direction == "rtl") @@ -2994,7 +3275,7 @@ private static XElement GetJustification(XElement blockLevelElement, HtmlToWmlCo { "left" => "right", "right" => "left", - _ => jc + _ => jc, }; } XElement jcElement = null; @@ -3010,16 +3291,16 @@ private class HeadingInfo }; private static readonly HeadingInfo[] HeadingTagMap = new[] - { - new HeadingInfo { Name = XhtmlNoNamespace.h1, StyleName = "Heading1" }, - new HeadingInfo { Name = XhtmlNoNamespace.h2, StyleName = "Heading2" }, - new HeadingInfo { Name = XhtmlNoNamespace.h3, StyleName = "Heading3" }, - new HeadingInfo { Name = XhtmlNoNamespace.h4, StyleName = "Heading4" }, - new HeadingInfo { Name = XhtmlNoNamespace.h5, StyleName = "Heading5" }, - new HeadingInfo { Name = XhtmlNoNamespace.h6, StyleName = "Heading6" }, - new HeadingInfo { Name = XhtmlNoNamespace.h7, StyleName = "Heading7" }, - new HeadingInfo { Name = XhtmlNoNamespace.h8, StyleName = "Heading8" }, - }; + { + new HeadingInfo { Name = XhtmlNoNamespace.h1, StyleName = "Heading1" }, + new HeadingInfo { Name = XhtmlNoNamespace.h2, StyleName = "Heading2" }, + new HeadingInfo { Name = XhtmlNoNamespace.h3, StyleName = "Heading3" }, + new HeadingInfo { Name = XhtmlNoNamespace.h4, StyleName = "Heading4" }, + new HeadingInfo { Name = XhtmlNoNamespace.h5, StyleName = "Heading5" }, + new HeadingInfo { Name = XhtmlNoNamespace.h6, StyleName = "Heading6" }, + new HeadingInfo { Name = XhtmlNoNamespace.h7, StyleName = "Heading7" }, + new HeadingInfo { Name = XhtmlNoNamespace.h8, StyleName = "Heading8" }, + }; private static string GetDirection(XElement element) { @@ -3039,20 +3320,21 @@ private static string GetDirection(XElement element) private static XElement GetTableProperties(XElement element) { - XElement bidiVisual = null; var direction = GetDirection(element); if (direction == "rtl") bidiVisual = new XElement(W.bidiVisual); - var tblPr = new XElement(W.tblPr, + var tblPr = new XElement( + W.tblPr, bidiVisual, GetTableWidth(element), GetTableCellSpacing(element), GetBlockContentBorders(element, W.tblBorders, false), GetTableShading(element), GetTableCellMargins(element), - GetTableLook(element)); + GetTableLook(element) + ); return tblPr; } @@ -3073,13 +3355,13 @@ private static XElement GetTableWidth(XElement element) var width = element.GetProp("width"); if (width.IsAuto) { - return new XElement(W.tblW, - new XAttribute(W._w, "0"), - new XAttribute(W.type, "auto")); + return new XElement(W.tblW, new XAttribute(W._w, "0"), new XAttribute(W.type, "auto")); } - var widthElement = new XElement(W.tblW, + var widthElement = new XElement( + W.tblW, new XAttribute(W._w, (long)(Twip)width), - new XAttribute(W.type, "dxa")); + new XAttribute(W.type, "dxa") + ); return widthElement; } @@ -3088,25 +3370,33 @@ private static XElement GetCellWidth(XElement element) var width = element.GetProp("width"); if (width.IsAuto) { - return new XElement(W.tcW, - new XAttribute(W._w, "0"), - new XAttribute(W.type, "auto")); + return new XElement(W.tcW, new XAttribute(W._w, "0"), new XAttribute(W.type, "auto")); } - var widthElement = new XElement(W.tcW, + var widthElement = new XElement( + W.tcW, new XAttribute(W._w, (long)(Twip)width), - new XAttribute(W.type, "dxa")); + new XAttribute(W.type, "dxa") + ); return widthElement; } private static XElement GetBlockContentBorders(XElement element, XName borderXName, bool forParagraph) { - if ((element.Name == XhtmlNoNamespace.td || element.Name == XhtmlNoNamespace.th || element.Name == XhtmlNoNamespace.caption) && forParagraph) + if ( + ( + element.Name == XhtmlNoNamespace.td + || element.Name == XhtmlNoNamespace.th + || element.Name == XhtmlNoNamespace.caption + ) && forParagraph + ) return null; - var borders = new XElement(borderXName, + var borders = new XElement( + borderXName, new XElement(W.top, GetBorderAttributes(element, "top")), new XElement(W.left, GetBorderAttributes(element, "left")), new XElement(W.bottom, GetBorderAttributes(element, "bottom")), - new XElement(W.right, GetBorderAttributes(element, "right"))); + new XElement(W.right, GetBorderAttributes(element, "right")) + ); if (borders.Elements().Attributes(W.val).Where(v => (string)v == "none").Count() == 4) return null; return borders; @@ -3200,13 +3490,7 @@ private static List GetBorderAttributes(XElement element, string whi // sz is in 1/8 of a point // space is in 1/20 of a point - var attList = new List() - { - val, - sz, - space, - color, - }; + var attList = new List() { val, sz, space, color }; return attList; } @@ -3235,9 +3519,8 @@ private static XElement GetTableLook(XElement element) // w:noVBand='1' // xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'/>" -@"" - -); + @"" + ); tblLook.Attributes().Where(a => a.IsNamespaceDeclaration).Remove(); return tblLook; } @@ -3271,9 +3554,13 @@ private static XElement GetTableGrid(XElement element, HtmlToWmlConverterSetting columnWidths[c] = columnWidth; } - var tblGrid = new XElement(W.tblGrid, - columnWidths.Select(cw => new XElement(W.gridCol, - new XAttribute(W._w, (long)GetTwipWidth(cw, (int)printable))))); + var tblGrid = new XElement( + W.tblGrid, + columnWidths.Select(cw => new XElement( + W.gridCol, + new XAttribute(W._w, (long)GetTwipWidth(cw, (int)printable)) + )) + ); return tblGrid; } @@ -3298,8 +3585,15 @@ private static Twip GetTwipWidth(CssExpression columnWidth, int printable) private static XElement[][] GetTableArray(XElement table) { - var rowList = table.DescendantsTrimmed(XhtmlNoNamespace.table).Where(e => e.Name == XhtmlNoNamespace.tr).ToList(); - var numberColumns = rowList.Select(r => r.Elements().Where(e => e.Name == XhtmlNoNamespace.td || e.Name == XhtmlNoNamespace.th).Count()).Max(); + var rowList = table + .DescendantsTrimmed(XhtmlNoNamespace.table) + .Where(e => e.Name == XhtmlNoNamespace.tr) + .ToList(); + var numberColumns = rowList + .Select(r => + r.Elements().Where(e => e.Name == XhtmlNoNamespace.td || e.Name == XhtmlNoNamespace.th).Count() + ) + .Max(); var tableArray = new XElement[rowList.Count][]; var rowNumber = 0; foreach (var row in rowList) @@ -3318,16 +3612,17 @@ private static XElement[][] GetTableArray(XElement table) private static XElement GetCellPropertiesForCaption(XElement element) { - var gridSpan = new XElement(W.gridSpan, - new XAttribute(W.val, 3)); + var gridSpan = new XElement(W.gridSpan, new XAttribute(W.val, 3)); var tcBorders = GetBlockContentBorders(element, W.tcBorders, false); if (tcBorders == null) - tcBorders = new XElement(W.tcBorders, + tcBorders = new XElement( + W.tcBorders, new XElement(W.top, new XAttribute(W.val, "nil")), new XElement(W.left, new XAttribute(W.val, "nil")), new XElement(W.bottom, new XAttribute(W.val, "nil")), - new XElement(W.right, new XAttribute(W.val, "nil"))); + new XElement(W.right, new XAttribute(W.val, "nil")) + ); var shd = GetCellShading(element); @@ -3338,13 +3633,7 @@ private static XElement GetCellPropertiesForCaption(XElement element) var vAlign = new XElement(W.vAlign, new XAttribute(W.val, "center")); - return new XElement(W.tcPr, - gridSpan, - tcBorders, - shd, - tcMar, - vAlign, - hideMark); + return new XElement(W.tcPr, gridSpan, tcBorders, shd, tcMar, vAlign, hideMark); } private static XElement GetCellProperties(XElement element) @@ -3352,8 +3641,7 @@ private static XElement GetCellProperties(XElement element) var colspan = (int?)element.Attribute(XhtmlNoNamespace.colspan); XElement gridSpan = null; if (colspan != null) - gridSpan = new XElement(W.gridSpan, - new XAttribute(W.val, colspan)); + gridSpan = new XElement(W.gridSpan, new XAttribute(W.val, colspan)); var tblW = GetCellWidth(element); @@ -3371,10 +3659,8 @@ private static XElement GetCellProperties(XElement element) XElement vMerge = null; if (element.Attribute("HtmlToWmlVMergeNoRestart") != null) vMerge = new XElement(W.vMerge); - else - if (element.Attribute("HtmlToWmlVMergeRestart") != null) - vMerge = new XElement(W.vMerge, - new XAttribute(W.val, "restart")); + else if (element.Attribute("HtmlToWmlVMergeRestart") != null) + vMerge = new XElement(W.vMerge, new XAttribute(W.val, "restart")); var vAlignValue = (string)element.Attribute(XhtmlNoNamespace.valign); var verticalAlignmentProp = element.GetProp("vertical-align"); @@ -3387,15 +3673,7 @@ private static XElement GetCellProperties(XElement element) vAlign = new XElement(W.vAlign, new XAttribute(W.val, vAlignValue)); } - return new XElement(W.tcPr, - tblW, - gridSpan, - vMerge, - tcBorders, - shd, - tcMar, - vAlign, - hideMark); + return new XElement(W.tcPr, tblW, gridSpan, vMerge, tcBorders, shd, tcMar, vAlign, hideMark); } private static XElement GetCellHeaderProperties(XElement element) @@ -3419,13 +3697,7 @@ private static XElement GetCellHeaderProperties(XElement element) var vAlign = new XElement(W.vAlign, new XAttribute(W.val, "center")); - return new XElement(W.tcPr, - tblW, - tcBorders, - shd, - tcMar, - vAlign, - hideMark); + return new XElement(W.tcPr, tblW, tcBorders, shd, tcMar, vAlign, hideMark); } private static XElement GetCellShading(XElement element) @@ -3433,10 +3705,12 @@ private static XElement GetCellShading(XElement element) var backgroundColorProp = element.GetProp("background-color"); if (backgroundColorProp != null && backgroundColorProp != "transparent") { - var shd = new XElement(W.shd, + var shd = new XElement( + W.shd, new XAttribute(W.val, "clear"), new XAttribute(W.color, "auto"), - new XAttribute(W.fill, backgroundColorProp)); + new XAttribute(W.fill, backgroundColorProp) + ); return shd; } return null; @@ -3448,33 +3722,29 @@ private static XElement GetCellMargins(XElement element) var leftProp = element.GetProp("padding-left"); var bottomProp = element.GetProp("padding-bottom"); var rightProp = element.GetProp("padding-right"); - if ((long)topProp == 0 && - (long)leftProp == 0 && - (long)bottomProp == 0 && - (long)rightProp == 0) + if ((long)topProp == 0 && (long)leftProp == 0 && (long)bottomProp == 0 && (long)rightProp == 0) return null; XElement top = null; if (topProp != null) - top = new XElement(W.top, - new XAttribute(W._w, (long)(Twip)topProp), - new XAttribute(W.type, "dxa")); + top = new XElement(W.top, new XAttribute(W._w, (long)(Twip)topProp), new XAttribute(W.type, "dxa")); XElement left = null; if (leftProp != null) - left = new XElement(W.left, - new XAttribute(W._w, (long)(Twip)leftProp), - new XAttribute(W.type, "dxa")); + left = new XElement(W.left, new XAttribute(W._w, (long)(Twip)leftProp), new XAttribute(W.type, "dxa")); XElement bottom = null; if (bottomProp != null) - bottom = new XElement(W.bottom, + bottom = new XElement( + W.bottom, new XAttribute(W._w, (long)(Twip)bottomProp), - new XAttribute(W.type, "dxa")); + new XAttribute(W.type, "dxa") + ); XElement right = null; if (rightProp != null) - right = new XElement(W.right, + right = new XElement( + W.right, new XAttribute(W._w, (long)(Twip)rightProp), - new XAttribute(W.type, "dxa")); - var tcMar = new XElement(W.tcMar, - top, left, bottom, right); + new XAttribute(W.type, "dxa") + ); + var tcMar = new XElement(W.tcMar, top, left, bottom, right); if (tcMar.Elements().Any()) return tcMar; return null; @@ -3506,10 +3776,32 @@ private static XElement GetTableCellSpacing(XElement element) var borderSpacing = table.GetProp("border-spacing"); var marginTopProperty = element.GetProp("margin-top"); if (marginTopProperty == null) - marginTopProperty = new CssExpression { Terms = new List { new CssTerm { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT } } }; + marginTopProperty = new CssExpression + { + Terms = new List + { + new CssTerm + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; var marginBottomProperty = element.GetProp("margin-bottom"); if (marginBottomProperty == null) - marginBottomProperty = new CssExpression { Terms = new List { new CssTerm { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT } } }; + marginBottomProperty = new CssExpression + { + Terms = new List + { + new CssTerm + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; var twips1 = (Twip)marginTopProperty; var twips2 = (Twip)marginBottomProperty; Twip minTwips = 15; @@ -3520,10 +3812,12 @@ private static XElement GetTableCellSpacing(XElement element) // have to divide twipToUse by 2 because border-spacing specifies the space between the border of once cell and its adjacent. // tblCellSpacing specifies the distance between the border and the half way point between two cells. var twipToUseOverTwo = twipToUse / 2; - tblCellSpacing = new XElement(W.tblCellSpacing, new XAttribute(W._w, twipToUseOverTwo), - new XAttribute(W.type, "dxa")); + tblCellSpacing = new XElement( + W.tblCellSpacing, + new XAttribute(W._w, twipToUseOverTwo), + new XAttribute(W.type, "dxa") + ); } - } return tblCellSpacing; } @@ -3532,7 +3826,7 @@ private static XElement GetTableCellMargins(XElement element) { // todo very incomplete var tblCellMar = XElement.Parse( -@" + @" -"); +" + ); tblCellMar.Attributes().Where(a => a.IsNamespaceDeclaration).Remove(); return tblCellMar; } @@ -3574,8 +3869,7 @@ private static XElement GetTableRowProperties(XElement element) if (cellHeights.Any()) { var max = cellHeights.Max(); - trHeight = new XElement(W.trHeight, - new XAttribute(W.val, max)); + trHeight = new XElement(W.trHeight, new XAttribute(W.val, max)); } var borderCollapseProperty = table.GetProp("border-collapse"); @@ -3583,9 +3877,7 @@ private static XElement GetTableRowProperties(XElement element) if (borderCollapseProperty != null && borderCollapseProperty != "collapse") borderCollapse = GetTableCellSpacing(element); - trPr = new XElement(W.trPr, - GetTableCellSpacing(element), - trHeight); + trPr = new XElement(W.trPr, GetTableCellSpacing(element), trHeight); if (trPr.Elements().Any()) return trPr; } @@ -3599,412 +3891,410 @@ private static XAttribute GetXmlSpaceAttribute(string value) return null; } - private static readonly Dictionary InstalledFonts = new Dictionary - { - {"serif", "Times New Roman"}, - {"sans-serif", "Arial"}, - {"cursive", "Kunstler Script"}, - {"fantasy", "Curlz MT"}, - {"monospace", "Courier New"}, - - {"agency fb", "Agency FB"}, - {"agencyfb", "Agency FB"}, - {"aharoni", "Aharoni"}, - {"algerian", "Algerian"}, - {"andalus", "Andalus"}, - {"angsana new", "Angsana New"}, - {"angsananew", "Angsana New"}, - {"angsanaupc", "AngsanaUPC"}, - {"aparajita", "Aparajita"}, - {"arabic typesetting", "Arabic Typesetting"}, - {"arabictypesetting", "Arabic Typesetting"}, - {"arial", "Arial"}, - {"arial black", "Arial Black"}, - {"arial narrow", "Arial Narrow"}, - {"arial rounded mt bold", "Arial Rounded MT Bold"}, - {"arial unicode ms", "Arial Unicode MS"}, - {"arialblack", "Arial Black"}, - {"arialnarrow", "Arial Narrow"}, - {"arialroundedmtbold", "Arial Rounded MT Bold"}, - {"arialunicodems", "Arial Unicode MS"}, - {"baskerville old face", "Baskerville Old Face"}, - {"baskervilleoldface", "Baskerville Old Face"}, - {"batang", "Batang"}, - {"batangche", "BatangChe"}, - {"bauhaus 93", "Bauhaus 93"}, - {"bauhaus93", "Bauhaus 93"}, - {"bell mt", "Bell MT"}, - {"bellmt", "Bell MT"}, - {"berlin sans fb", "Berlin Sans FB"}, - {"berlin sans fb demi", "Berlin Sans FB Demi"}, - {"berlinsansfb", "Berlin Sans FB"}, - {"berlinsansfbdemi", "Berlin Sans FB Demi"}, - {"bernard mt condensed", "Bernard MT Condensed"}, - {"bernardmtcondensed", "Bernard MT Condensed"}, - {"blackadder itc", "Blackadder ITC"}, - {"blackadderitc", "Blackadder ITC"}, - {"bodoni mt", "Bodoni MT"}, - {"bodoni mt black", "Bodoni MT Black"}, - {"bodoni mt condensed", "Bodoni MT Condensed"}, - {"bodoni mt poster compressed", "Bodoni MT Poster Compressed"}, - {"bodonimt", "Bodoni MT"}, - {"bodonimtblack", "Bodoni MT Black"}, - {"bodonimtcondensed", "Bodoni MT Condensed"}, - {"bodonimtpostercompressed", "Bodoni MT Poster Compressed"}, - {"book antiqua", "Book Antiqua"}, - {"bookantiqua", "Book Antiqua"}, - {"bookman old style", "Bookman Old Style"}, - {"bookmanoldstyle", "Bookman Old Style"}, - {"bookshelf symbol 7", "Bookshelf Symbol 7"}, - {"bookshelfsymbol7", "Bookshelf Symbol 7"}, - {"bradley hand itc", "Bradley Hand ITC"}, - {"bradleyhanditc", "Bradley Hand ITC"}, - {"britannic bold", "Britannic Bold"}, - {"britannicbold", "Britannic Bold"}, - {"broadway", "Broadway"}, - {"browallia new", "Browallia New"}, - {"browallianew", "Browallia New"}, - {"browalliaupc", "BrowalliaUPC"}, - {"brush script mt", "Brush Script MT"}, - {"brushscriptmt", "Brush Script MT"}, - {"calibri", "Calibri"}, - {"californian fb", "Californian FB"}, - {"californianfb", "Californian FB"}, - {"calisto mt", "Calisto MT"}, - {"calistomt", "Calisto MT"}, - {"cambria", "Cambria"}, - {"cambria math", "Cambria Math"}, - {"cambriamath", "Cambria Math"}, - {"candara", "Candara"}, - {"castellar", "Castellar"}, - {"centaur", "Centaur"}, - {"century", "Century"}, - {"century gothic", "Century Gothic"}, - {"century schoolbook", "Century Schoolbook"}, - {"centurygothic", "Century Gothic"}, - {"centuryschoolbook", "Century Schoolbook"}, - {"chiller", "Chiller"}, - {"colonna mt", "Colonna MT"}, - {"colonnamt", "Colonna MT"}, - {"comic sans ms", "Comic Sans MS"}, - {"comicsansms", "Comic Sans MS"}, - {"consolas", "Consolas"}, - {"constantia", "Constantia"}, - {"cooper black", "Cooper Black"}, - {"cooperblack", "Cooper Black"}, - {"copperplate gothic bold", "Copperplate Gothic Bold"}, - {"copperplate gothic light", "Copperplate Gothic Light"}, - {"copperplategothicbold", "Copperplate Gothic Bold"}, - {"copperplategothiclight", "Copperplate Gothic Light"}, - {"corbel", "Corbel"}, - {"cordia new", "Cordia New"}, - {"cordianew", "Cordia New"}, - {"cordiaupc", "CordiaUPC"}, - {"courier new", "Courier New"}, - {"couriernew", "Courier New"}, - {"curlz mt", "Curlz MT"}, - {"curlzmt", "Curlz MT"}, - {"daunpenh", "DaunPenh"}, - {"david", "David"}, - {"dfkai-sb", "DFKai-SB"}, - {"dilleniaupc", "DilleniaUPC"}, - {"dokchampa", "DokChampa"}, - {"dotum", "Dotum"}, - {"dotumche", "DotumChe"}, - {"ebrima", "Ebrima"}, - {"edwardian script itc", "Edwardian Script ITC"}, - {"edwardianscriptitc", "Edwardian Script ITC"}, - {"elephant", "Elephant"}, - {"engravers mt", "Engravers MT"}, - {"engraversmt", "Engravers MT"}, - {"eras bold itc", "Eras Bold ITC"}, - {"eras demi itc", "Eras Demi ITC"}, - {"eras light itc", "Eras Light ITC"}, - {"eras medium itc", "Eras Medium ITC"}, - {"erasbolditc", "Eras Bold ITC"}, - {"erasdemiitc", "Eras Demi ITC"}, - {"eraslightitc", "Eras Light ITC"}, - {"erasmediumitc", "Eras Medium ITC"}, - {"estrangelo edessa", "Estrangelo Edessa"}, - {"estrangeloedessa", "Estrangelo Edessa"}, - {"eucrosiaupc", "EucrosiaUPC"}, - {"euphemia", "Euphemia"}, - {"fangsong", "FangSong"}, - {"felix titling", "Felix Titling"}, - {"felixtitling", "Felix Titling"}, - {"footlight mt light", "Footlight MT Light"}, - {"footlightmtlight", "Footlight MT Light"}, - {"forte", "Forte"}, - {"franklin gothic book", "Franklin Gothic Book"}, - {"franklin gothic demi", "Franklin Gothic Demi"}, - {"franklin gothic demi cond", "Franklin Gothic Demi Cond"}, - {"franklin gothic heavy", "Franklin Gothic Heavy"}, - {"franklin gothic medium", "Franklin Gothic Medium"}, - {"franklin gothic medium cond", "Franklin Gothic Medium Cond"}, - {"franklingothicbook", "Franklin Gothic Book"}, - {"franklingothicdemi", "Franklin Gothic Demi"}, - {"franklingothicdemicond", "Franklin Gothic Demi Cond"}, - {"franklingothicheavy", "Franklin Gothic Heavy"}, - {"franklingothicmedium", "Franklin Gothic Medium"}, - {"franklingothicmediumcond", "Franklin Gothic Medium Cond"}, - {"frankruehl", "FrankRuehl"}, - {"freesiaupc", "FreesiaUPC"}, - {"freestyle script", "Freestyle Script"}, - {"freestylescript", "Freestyle Script"}, - {"french script mt", "French Script MT"}, - {"frenchscriptmt", "French Script MT"}, - {"gabriola", "Gabriola"}, - {"garamond", "Garamond"}, - {"gautami", "Gautami"}, - {"georgia", "Georgia"}, - {"gigi", "Gigi"}, - {"gill sans mt", "Gill Sans MT"}, - {"gill sans mt condensed", "Gill Sans MT Condensed"}, - {"gill sans mt ext condensed bold", "Gill Sans MT Ext Condensed Bold"}, - {"gill sans ultra bold", "Gill Sans Ultra Bold"}, - {"gill sans ultra bold condensed", "Gill Sans Ultra Bold Condensed"}, - {"gillsansmt", "Gill Sans MT"}, - {"gillsansmtcondensed", "Gill Sans MT Condensed"}, - {"gillsansmtextcondensedbold", "Gill Sans MT Ext Condensed Bold"}, - {"gillsansultrabold", "Gill Sans Ultra Bold"}, - {"gillsansultraboldcondensed", "Gill Sans Ultra Bold Condensed"}, - {"gisha", "Gisha"}, - {"gloucester mt extra condensed", "Gloucester MT Extra Condensed"}, - {"gloucestermtextracondensed", "Gloucester MT Extra Condensed"}, - {"goudy old style", "Goudy Old Style"}, - {"goudy stout", "Goudy Stout"}, - {"goudyoldstyle", "Goudy Old Style"}, - {"goudystout", "Goudy Stout"}, - {"gulim", "Gulim"}, - {"gulimche", "GulimChe"}, - {"gungsuh", "Gungsuh"}, - {"gungsuhche", "GungsuhChe"}, - {"haettenschweiler", "Haettenschweiler"}, - {"harlow solid italic", "Harlow Solid Italic"}, - {"harlowsoliditalic", "Harlow Solid Italic"}, - {"harrington", "Harrington"}, - {"high tower text", "High Tower Text"}, - {"hightowertext", "High Tower Text"}, - {"impact", "Impact"}, - {"imprint mt shadow", "Imprint MT Shadow"}, - {"imprintmtshadow", "Imprint MT Shadow"}, - {"informal roman", "Informal Roman"}, - {"informalroman", "Informal Roman"}, - {"irisupc", "IrisUPC"}, - {"iskoola pota", "Iskoola Pota"}, - {"iskoolapota", "Iskoola Pota"}, - {"jasmineupc", "JasmineUPC"}, - {"jokerman", "Jokerman"}, - {"juice itc", "Juice ITC"}, - {"juiceitc", "Juice ITC"}, - {"kaiti", "KaiTi"}, - {"kalinga", "Kalinga"}, - {"kartika", "Kartika"}, - {"khmer ui", "Khmer UI"}, - {"khmerui", "Khmer UI"}, - {"kodchiangupc", "KodchiangUPC"}, - {"kokila", "Kokila"}, - {"kristen itc", "Kristen ITC"}, - {"kristenitc", "Kristen ITC"}, - {"kunstler script", "Kunstler Script"}, - {"kunstlerscript", "Kunstler Script"}, - {"lao ui", "Lao UI"}, - {"laoui", "Lao UI"}, - {"latha", "Latha"}, - {"leelawadee", "Leelawadee"}, - {"levenim mt", "Levenim MT"}, - {"levenimmt", "Levenim MT"}, - {"lilyupc", "LilyUPC"}, - {"lucida bright", "Lucida Bright"}, - {"lucida calligraphy", "Lucida Calligraphy"}, - {"lucida console", "Lucida Console"}, - {"lucida fax", "Lucida Fax"}, - {"lucida handwriting", "Lucida Handwriting"}, - {"lucida sans", "Lucida Sans"}, - {"lucida sans typewriter", "Lucida Sans Typewriter"}, - {"lucida sans unicode", "Lucida Sans Unicode"}, - {"lucidabright", "Lucida Bright"}, - {"lucidacalligraphy", "Lucida Calligraphy"}, - {"lucidaconsole", "Lucida Console"}, - {"lucidafax", "Lucida Fax"}, - {"lucidahandwriting", "Lucida Handwriting"}, - {"lucidasans", "Lucida Sans"}, - {"lucidasanstypewriter", "Lucida Sans Typewriter"}, - {"lucidasansunicode", "Lucida Sans Unicode"}, - {"magneto", "Magneto"}, - {"maiandra gd", "Maiandra GD"}, - {"maiandragd", "Maiandra GD"}, - {"malgun gothic", "Malgun Gothic"}, - {"malgungothic", "Malgun Gothic"}, - {"mangal", "Mangal"}, - {"marlett", "Marlett"}, - {"matura mt script capitals", "Matura MT Script Capitals"}, - {"maturamtscriptcapitals", "Matura MT Script Capitals"}, - {"meiryo", "Meiryo"}, - {"meiryo ui", "Meiryo UI"}, - {"meiryoui", "Meiryo UI"}, - {"microsoft himalaya", "Microsoft Himalaya"}, - {"microsoft jhenghei", "Microsoft JhengHei"}, - {"microsoft new tai lue", "Microsoft New Tai Lue"}, - {"microsoft phagspa", "Microsoft PhagsPa"}, - {"microsoft sans serif", "Microsoft Sans Serif"}, - {"microsoft tai le", "Microsoft Tai Le"}, - {"microsoft uighur", "Microsoft Uighur"}, - {"microsoft yahei", "Microsoft YaHei"}, - {"microsoft yi baiti", "Microsoft Yi Baiti"}, - {"microsofthimalaya", "Microsoft Himalaya"}, - {"microsoftjhenghei", "Microsoft JhengHei"}, - {"microsoftnewtailue", "Microsoft New Tai Lue"}, - {"microsoftphagspa", "Microsoft PhagsPa"}, - {"microsoftsansserif", "Microsoft Sans Serif"}, - {"microsofttaile", "Microsoft Tai Le"}, - {"microsoftuighur", "Microsoft Uighur"}, - {"microsoftyahei", "Microsoft YaHei"}, - {"microsoftyibaiti", "Microsoft Yi Baiti"}, - {"mingliu", "MingLiU"}, - {"mingliu_hkscs", "MingLiU_HKSCS"}, - {"mingliu_hkscs-extb", "MingLiU_HKSCS-ExtB"}, - {"mingliu-extb", "MingLiU-ExtB"}, - {"miriam", "Miriam"}, - {"miriam fixed", "Miriam Fixed"}, - {"miriamfixed", "Miriam Fixed"}, - {"mistral", "Mistral"}, - {"modern no. 20", "Modern No. 20"}, - {"modernno.20", "Modern No. 20"}, - {"mongolian baiti", "Mongolian Baiti"}, - {"mongolianbaiti", "Mongolian Baiti"}, - {"monotype corsiva", "Monotype Corsiva"}, - {"monotypecorsiva", "Monotype Corsiva"}, - {"moolboran", "MoolBoran"}, - {"ms gothic", "MS Gothic"}, - {"ms mincho", "MS Mincho"}, - {"ms pgothic", "MS PGothic"}, - {"ms pmincho", "MS PMincho"}, - {"ms reference sans serif", "MS Reference Sans Serif"}, - {"ms reference specialty", "MS Reference Specialty"}, - {"ms ui gothic", "MS UI Gothic"}, - {"msgothic", "MS Gothic"}, - {"msmincho", "MS Mincho"}, - {"mspgothic", "MS PGothic"}, - {"mspmincho", "MS PMincho"}, - {"msreferencesansserif", "MS Reference Sans Serif"}, - {"msreferencespecialty", "MS Reference Specialty"}, - {"msuigothic", "MS UI Gothic"}, - {"mt extra", "MT Extra"}, - {"mtextra", "MT Extra"}, - {"mv boli", "MV Boli"}, - {"mvboli", "MV Boli"}, - {"narkisim", "Narkisim"}, - {"niagara engraved", "Niagara Engraved"}, - {"niagara solid", "Niagara Solid"}, - {"niagaraengraved", "Niagara Engraved"}, - {"niagarasolid", "Niagara Solid"}, - {"nsimsun", "NSimSun"}, - {"nyala", "Nyala"}, - {"ocr a extended", "OCR A Extended"}, - {"ocraextended", "OCR A Extended"}, - {"old english text mt", "Old English Text MT"}, - {"oldenglishtextmt", "Old English Text MT"}, - {"onyx", "Onyx"}, - {"palace script mt", "Palace Script MT"}, - {"palacescriptmt", "Palace Script MT"}, - {"palatino linotype", "Palatino Linotype"}, - {"palatinolinotype", "Palatino Linotype"}, - {"papyrus", "Papyrus"}, - {"parchment", "Parchment"}, - {"perpetua", "Perpetua"}, - {"perpetua titling mt", "Perpetua Titling MT"}, - {"perpetuatitlingmt", "Perpetua Titling MT"}, - {"plantagenet cherokee", "Plantagenet Cherokee"}, - {"plantagenetcherokee", "Plantagenet Cherokee"}, - {"playbill", "Playbill"}, - {"pmingliu", "PMingLiU"}, - {"pmingliu-extb", "PMingLiU-ExtB"}, - {"poor richard", "Poor Richard"}, - {"poorrichard", "Poor Richard"}, - {"pristina", "Pristina"}, - {"raavi", "Raavi"}, - {"rage italic", "Rage Italic"}, - {"rageitalic", "Rage Italic"}, - {"ravie", "Ravie"}, - {"rockwell", "Rockwell"}, - {"rockwell condensed", "Rockwell Condensed"}, - {"rockwell extra bold", "Rockwell Extra Bold"}, - {"rockwellcondensed", "Rockwell Condensed"}, - {"rockwellextrabold", "Rockwell Extra Bold"}, - {"rod", "Rod"}, - {"sakkal majalla", "Sakkal Majalla"}, - {"sakkalmajalla", "Sakkal Majalla"}, - {"script mt bold", "Script MT Bold"}, - {"scriptmtbold", "Script MT Bold"}, - {"segoe print", "Segoe Print"}, - {"segoe script", "Segoe Script"}, - {"segoe ui", "Segoe UI"}, - {"segoe ui light", "Segoe UI Light"}, - {"segoe ui semibold", "Segoe UI Semibold"}, - {"segoe ui symbol", "Segoe UI Symbol"}, - {"segoeprint", "Segoe Print"}, - {"segoescript", "Segoe Script"}, - {"segoeui", "Segoe UI"}, - {"segoeuilight", "Segoe UI Light"}, - {"segoeuisemibold", "Segoe UI Semibold"}, - {"segoeuisymbol", "Segoe UI Symbol"}, - {"shonar bangla", "Shonar Bangla"}, - {"shonarbangla", "Shonar Bangla"}, - {"showcard gothic", "Showcard Gothic"}, - {"showcardgothic", "Showcard Gothic"}, - {"shruti", "Shruti"}, - {"simhei", "SimHei"}, - {"simplified arabic", "Simplified Arabic"}, - {"simplified arabic fixed", "Simplified Arabic Fixed"}, - {"simplifiedarabic", "Simplified Arabic"}, - {"simplifiedarabicfixed", "Simplified Arabic Fixed"}, - {"simsun", "SimSun"}, - {"simsun-extb", "SimSun-ExtB"}, - {"snap itc", "Snap ITC"}, - {"snapitc", "Snap ITC"}, - {"stencil", "Stencil"}, - {"swgamekeys mt", "SWGamekeys MT"}, - {"swgamekeysmt", "SWGamekeys MT"}, - {"swmacro", "SWMacro"}, - {"sylfaen", "Sylfaen"}, - {"symbol", "Symbol"}, - {"tahoma", "Tahoma"}, - {"tempus sans itc", "Tempus Sans ITC"}, - {"tempussansitc", "Tempus Sans ITC"}, - {"times new roman", "Times New Roman"}, - {"timesnewroman", "Times New Roman"}, - {"traditional arabic", "Traditional Arabic"}, - {"traditionalarabic", "Traditional Arabic"}, - {"trebuchet ms", "Trebuchet MS"}, - {"trebuchetms", "Trebuchet MS"}, - {"tunga", "Tunga"}, - {"tw cen mt", "Tw Cen MT"}, - {"tw cen mt condensed", "Tw Cen MT Condensed"}, - {"tw cen mt condensed extra bold", "Tw Cen MT Condensed Extra Bold"}, - {"twcenmt", "Tw Cen MT"}, - {"twcenmtcondensed", "Tw Cen MT Condensed"}, - {"twcenmtcondensedextrabold", "Tw Cen MT Condensed Extra Bold"}, - {"utsaah", "Utsaah"}, - {"vani", "Vani"}, - {"verdana", "Verdana"}, - {"vijaya", "Vijaya"}, - {"viner hand itc", "Viner Hand ITC"}, - {"vinerhanditc", "Viner Hand ITC"}, - {"vivaldi", "Vivaldi"}, - {"vladimir script", "Vladimir Script"}, - {"vladimirscript", "Vladimir Script"}, - {"vrinda", "Vrinda"}, - {"webdings", "Webdings"}, - {"wide latin", "Wide Latin"}, - {"widelatin", "Wide Latin"}, - {"wingdings", "Wingdings"}, - {"wingdings 2", "Wingdings 2"}, - {"wingdings 3", "Wingdings 3"}, - {"wingdings2", "Wingdings 2"}, - {"wingdings3", "Wingdings 3"}, - }; + { + { "serif", "Times New Roman" }, + { "sans-serif", "Arial" }, + { "cursive", "Kunstler Script" }, + { "fantasy", "Curlz MT" }, + { "monospace", "Courier New" }, + { "agency fb", "Agency FB" }, + { "agencyfb", "Agency FB" }, + { "aharoni", "Aharoni" }, + { "algerian", "Algerian" }, + { "andalus", "Andalus" }, + { "angsana new", "Angsana New" }, + { "angsananew", "Angsana New" }, + { "angsanaupc", "AngsanaUPC" }, + { "aparajita", "Aparajita" }, + { "arabic typesetting", "Arabic Typesetting" }, + { "arabictypesetting", "Arabic Typesetting" }, + { "arial", "Arial" }, + { "arial black", "Arial Black" }, + { "arial narrow", "Arial Narrow" }, + { "arial rounded mt bold", "Arial Rounded MT Bold" }, + { "arial unicode ms", "Arial Unicode MS" }, + { "arialblack", "Arial Black" }, + { "arialnarrow", "Arial Narrow" }, + { "arialroundedmtbold", "Arial Rounded MT Bold" }, + { "arialunicodems", "Arial Unicode MS" }, + { "baskerville old face", "Baskerville Old Face" }, + { "baskervilleoldface", "Baskerville Old Face" }, + { "batang", "Batang" }, + { "batangche", "BatangChe" }, + { "bauhaus 93", "Bauhaus 93" }, + { "bauhaus93", "Bauhaus 93" }, + { "bell mt", "Bell MT" }, + { "bellmt", "Bell MT" }, + { "berlin sans fb", "Berlin Sans FB" }, + { "berlin sans fb demi", "Berlin Sans FB Demi" }, + { "berlinsansfb", "Berlin Sans FB" }, + { "berlinsansfbdemi", "Berlin Sans FB Demi" }, + { "bernard mt condensed", "Bernard MT Condensed" }, + { "bernardmtcondensed", "Bernard MT Condensed" }, + { "blackadder itc", "Blackadder ITC" }, + { "blackadderitc", "Blackadder ITC" }, + { "bodoni mt", "Bodoni MT" }, + { "bodoni mt black", "Bodoni MT Black" }, + { "bodoni mt condensed", "Bodoni MT Condensed" }, + { "bodoni mt poster compressed", "Bodoni MT Poster Compressed" }, + { "bodonimt", "Bodoni MT" }, + { "bodonimtblack", "Bodoni MT Black" }, + { "bodonimtcondensed", "Bodoni MT Condensed" }, + { "bodonimtpostercompressed", "Bodoni MT Poster Compressed" }, + { "book antiqua", "Book Antiqua" }, + { "bookantiqua", "Book Antiqua" }, + { "bookman old style", "Bookman Old Style" }, + { "bookmanoldstyle", "Bookman Old Style" }, + { "bookshelf symbol 7", "Bookshelf Symbol 7" }, + { "bookshelfsymbol7", "Bookshelf Symbol 7" }, + { "bradley hand itc", "Bradley Hand ITC" }, + { "bradleyhanditc", "Bradley Hand ITC" }, + { "britannic bold", "Britannic Bold" }, + { "britannicbold", "Britannic Bold" }, + { "broadway", "Broadway" }, + { "browallia new", "Browallia New" }, + { "browallianew", "Browallia New" }, + { "browalliaupc", "BrowalliaUPC" }, + { "brush script mt", "Brush Script MT" }, + { "brushscriptmt", "Brush Script MT" }, + { "calibri", "Calibri" }, + { "californian fb", "Californian FB" }, + { "californianfb", "Californian FB" }, + { "calisto mt", "Calisto MT" }, + { "calistomt", "Calisto MT" }, + { "cambria", "Cambria" }, + { "cambria math", "Cambria Math" }, + { "cambriamath", "Cambria Math" }, + { "candara", "Candara" }, + { "castellar", "Castellar" }, + { "centaur", "Centaur" }, + { "century", "Century" }, + { "century gothic", "Century Gothic" }, + { "century schoolbook", "Century Schoolbook" }, + { "centurygothic", "Century Gothic" }, + { "centuryschoolbook", "Century Schoolbook" }, + { "chiller", "Chiller" }, + { "colonna mt", "Colonna MT" }, + { "colonnamt", "Colonna MT" }, + { "comic sans ms", "Comic Sans MS" }, + { "comicsansms", "Comic Sans MS" }, + { "consolas", "Consolas" }, + { "constantia", "Constantia" }, + { "cooper black", "Cooper Black" }, + { "cooperblack", "Cooper Black" }, + { "copperplate gothic bold", "Copperplate Gothic Bold" }, + { "copperplate gothic light", "Copperplate Gothic Light" }, + { "copperplategothicbold", "Copperplate Gothic Bold" }, + { "copperplategothiclight", "Copperplate Gothic Light" }, + { "corbel", "Corbel" }, + { "cordia new", "Cordia New" }, + { "cordianew", "Cordia New" }, + { "cordiaupc", "CordiaUPC" }, + { "courier new", "Courier New" }, + { "couriernew", "Courier New" }, + { "curlz mt", "Curlz MT" }, + { "curlzmt", "Curlz MT" }, + { "daunpenh", "DaunPenh" }, + { "david", "David" }, + { "dfkai-sb", "DFKai-SB" }, + { "dilleniaupc", "DilleniaUPC" }, + { "dokchampa", "DokChampa" }, + { "dotum", "Dotum" }, + { "dotumche", "DotumChe" }, + { "ebrima", "Ebrima" }, + { "edwardian script itc", "Edwardian Script ITC" }, + { "edwardianscriptitc", "Edwardian Script ITC" }, + { "elephant", "Elephant" }, + { "engravers mt", "Engravers MT" }, + { "engraversmt", "Engravers MT" }, + { "eras bold itc", "Eras Bold ITC" }, + { "eras demi itc", "Eras Demi ITC" }, + { "eras light itc", "Eras Light ITC" }, + { "eras medium itc", "Eras Medium ITC" }, + { "erasbolditc", "Eras Bold ITC" }, + { "erasdemiitc", "Eras Demi ITC" }, + { "eraslightitc", "Eras Light ITC" }, + { "erasmediumitc", "Eras Medium ITC" }, + { "estrangelo edessa", "Estrangelo Edessa" }, + { "estrangeloedessa", "Estrangelo Edessa" }, + { "eucrosiaupc", "EucrosiaUPC" }, + { "euphemia", "Euphemia" }, + { "fangsong", "FangSong" }, + { "felix titling", "Felix Titling" }, + { "felixtitling", "Felix Titling" }, + { "footlight mt light", "Footlight MT Light" }, + { "footlightmtlight", "Footlight MT Light" }, + { "forte", "Forte" }, + { "franklin gothic book", "Franklin Gothic Book" }, + { "franklin gothic demi", "Franklin Gothic Demi" }, + { "franklin gothic demi cond", "Franklin Gothic Demi Cond" }, + { "franklin gothic heavy", "Franklin Gothic Heavy" }, + { "franklin gothic medium", "Franklin Gothic Medium" }, + { "franklin gothic medium cond", "Franklin Gothic Medium Cond" }, + { "franklingothicbook", "Franklin Gothic Book" }, + { "franklingothicdemi", "Franklin Gothic Demi" }, + { "franklingothicdemicond", "Franklin Gothic Demi Cond" }, + { "franklingothicheavy", "Franklin Gothic Heavy" }, + { "franklingothicmedium", "Franklin Gothic Medium" }, + { "franklingothicmediumcond", "Franklin Gothic Medium Cond" }, + { "frankruehl", "FrankRuehl" }, + { "freesiaupc", "FreesiaUPC" }, + { "freestyle script", "Freestyle Script" }, + { "freestylescript", "Freestyle Script" }, + { "french script mt", "French Script MT" }, + { "frenchscriptmt", "French Script MT" }, + { "gabriola", "Gabriola" }, + { "garamond", "Garamond" }, + { "gautami", "Gautami" }, + { "georgia", "Georgia" }, + { "gigi", "Gigi" }, + { "gill sans mt", "Gill Sans MT" }, + { "gill sans mt condensed", "Gill Sans MT Condensed" }, + { "gill sans mt ext condensed bold", "Gill Sans MT Ext Condensed Bold" }, + { "gill sans ultra bold", "Gill Sans Ultra Bold" }, + { "gill sans ultra bold condensed", "Gill Sans Ultra Bold Condensed" }, + { "gillsansmt", "Gill Sans MT" }, + { "gillsansmtcondensed", "Gill Sans MT Condensed" }, + { "gillsansmtextcondensedbold", "Gill Sans MT Ext Condensed Bold" }, + { "gillsansultrabold", "Gill Sans Ultra Bold" }, + { "gillsansultraboldcondensed", "Gill Sans Ultra Bold Condensed" }, + { "gisha", "Gisha" }, + { "gloucester mt extra condensed", "Gloucester MT Extra Condensed" }, + { "gloucestermtextracondensed", "Gloucester MT Extra Condensed" }, + { "goudy old style", "Goudy Old Style" }, + { "goudy stout", "Goudy Stout" }, + { "goudyoldstyle", "Goudy Old Style" }, + { "goudystout", "Goudy Stout" }, + { "gulim", "Gulim" }, + { "gulimche", "GulimChe" }, + { "gungsuh", "Gungsuh" }, + { "gungsuhche", "GungsuhChe" }, + { "haettenschweiler", "Haettenschweiler" }, + { "harlow solid italic", "Harlow Solid Italic" }, + { "harlowsoliditalic", "Harlow Solid Italic" }, + { "harrington", "Harrington" }, + { "high tower text", "High Tower Text" }, + { "hightowertext", "High Tower Text" }, + { "impact", "Impact" }, + { "imprint mt shadow", "Imprint MT Shadow" }, + { "imprintmtshadow", "Imprint MT Shadow" }, + { "informal roman", "Informal Roman" }, + { "informalroman", "Informal Roman" }, + { "irisupc", "IrisUPC" }, + { "iskoola pota", "Iskoola Pota" }, + { "iskoolapota", "Iskoola Pota" }, + { "jasmineupc", "JasmineUPC" }, + { "jokerman", "Jokerman" }, + { "juice itc", "Juice ITC" }, + { "juiceitc", "Juice ITC" }, + { "kaiti", "KaiTi" }, + { "kalinga", "Kalinga" }, + { "kartika", "Kartika" }, + { "khmer ui", "Khmer UI" }, + { "khmerui", "Khmer UI" }, + { "kodchiangupc", "KodchiangUPC" }, + { "kokila", "Kokila" }, + { "kristen itc", "Kristen ITC" }, + { "kristenitc", "Kristen ITC" }, + { "kunstler script", "Kunstler Script" }, + { "kunstlerscript", "Kunstler Script" }, + { "lao ui", "Lao UI" }, + { "laoui", "Lao UI" }, + { "latha", "Latha" }, + { "leelawadee", "Leelawadee" }, + { "levenim mt", "Levenim MT" }, + { "levenimmt", "Levenim MT" }, + { "lilyupc", "LilyUPC" }, + { "lucida bright", "Lucida Bright" }, + { "lucida calligraphy", "Lucida Calligraphy" }, + { "lucida console", "Lucida Console" }, + { "lucida fax", "Lucida Fax" }, + { "lucida handwriting", "Lucida Handwriting" }, + { "lucida sans", "Lucida Sans" }, + { "lucida sans typewriter", "Lucida Sans Typewriter" }, + { "lucida sans unicode", "Lucida Sans Unicode" }, + { "lucidabright", "Lucida Bright" }, + { "lucidacalligraphy", "Lucida Calligraphy" }, + { "lucidaconsole", "Lucida Console" }, + { "lucidafax", "Lucida Fax" }, + { "lucidahandwriting", "Lucida Handwriting" }, + { "lucidasans", "Lucida Sans" }, + { "lucidasanstypewriter", "Lucida Sans Typewriter" }, + { "lucidasansunicode", "Lucida Sans Unicode" }, + { "magneto", "Magneto" }, + { "maiandra gd", "Maiandra GD" }, + { "maiandragd", "Maiandra GD" }, + { "malgun gothic", "Malgun Gothic" }, + { "malgungothic", "Malgun Gothic" }, + { "mangal", "Mangal" }, + { "marlett", "Marlett" }, + { "matura mt script capitals", "Matura MT Script Capitals" }, + { "maturamtscriptcapitals", "Matura MT Script Capitals" }, + { "meiryo", "Meiryo" }, + { "meiryo ui", "Meiryo UI" }, + { "meiryoui", "Meiryo UI" }, + { "microsoft himalaya", "Microsoft Himalaya" }, + { "microsoft jhenghei", "Microsoft JhengHei" }, + { "microsoft new tai lue", "Microsoft New Tai Lue" }, + { "microsoft phagspa", "Microsoft PhagsPa" }, + { "microsoft sans serif", "Microsoft Sans Serif" }, + { "microsoft tai le", "Microsoft Tai Le" }, + { "microsoft uighur", "Microsoft Uighur" }, + { "microsoft yahei", "Microsoft YaHei" }, + { "microsoft yi baiti", "Microsoft Yi Baiti" }, + { "microsofthimalaya", "Microsoft Himalaya" }, + { "microsoftjhenghei", "Microsoft JhengHei" }, + { "microsoftnewtailue", "Microsoft New Tai Lue" }, + { "microsoftphagspa", "Microsoft PhagsPa" }, + { "microsoftsansserif", "Microsoft Sans Serif" }, + { "microsofttaile", "Microsoft Tai Le" }, + { "microsoftuighur", "Microsoft Uighur" }, + { "microsoftyahei", "Microsoft YaHei" }, + { "microsoftyibaiti", "Microsoft Yi Baiti" }, + { "mingliu", "MingLiU" }, + { "mingliu_hkscs", "MingLiU_HKSCS" }, + { "mingliu_hkscs-extb", "MingLiU_HKSCS-ExtB" }, + { "mingliu-extb", "MingLiU-ExtB" }, + { "miriam", "Miriam" }, + { "miriam fixed", "Miriam Fixed" }, + { "miriamfixed", "Miriam Fixed" }, + { "mistral", "Mistral" }, + { "modern no. 20", "Modern No. 20" }, + { "modernno.20", "Modern No. 20" }, + { "mongolian baiti", "Mongolian Baiti" }, + { "mongolianbaiti", "Mongolian Baiti" }, + { "monotype corsiva", "Monotype Corsiva" }, + { "monotypecorsiva", "Monotype Corsiva" }, + { "moolboran", "MoolBoran" }, + { "ms gothic", "MS Gothic" }, + { "ms mincho", "MS Mincho" }, + { "ms pgothic", "MS PGothic" }, + { "ms pmincho", "MS PMincho" }, + { "ms reference sans serif", "MS Reference Sans Serif" }, + { "ms reference specialty", "MS Reference Specialty" }, + { "ms ui gothic", "MS UI Gothic" }, + { "msgothic", "MS Gothic" }, + { "msmincho", "MS Mincho" }, + { "mspgothic", "MS PGothic" }, + { "mspmincho", "MS PMincho" }, + { "msreferencesansserif", "MS Reference Sans Serif" }, + { "msreferencespecialty", "MS Reference Specialty" }, + { "msuigothic", "MS UI Gothic" }, + { "mt extra", "MT Extra" }, + { "mtextra", "MT Extra" }, + { "mv boli", "MV Boli" }, + { "mvboli", "MV Boli" }, + { "narkisim", "Narkisim" }, + { "niagara engraved", "Niagara Engraved" }, + { "niagara solid", "Niagara Solid" }, + { "niagaraengraved", "Niagara Engraved" }, + { "niagarasolid", "Niagara Solid" }, + { "nsimsun", "NSimSun" }, + { "nyala", "Nyala" }, + { "ocr a extended", "OCR A Extended" }, + { "ocraextended", "OCR A Extended" }, + { "old english text mt", "Old English Text MT" }, + { "oldenglishtextmt", "Old English Text MT" }, + { "onyx", "Onyx" }, + { "palace script mt", "Palace Script MT" }, + { "palacescriptmt", "Palace Script MT" }, + { "palatino linotype", "Palatino Linotype" }, + { "palatinolinotype", "Palatino Linotype" }, + { "papyrus", "Papyrus" }, + { "parchment", "Parchment" }, + { "perpetua", "Perpetua" }, + { "perpetua titling mt", "Perpetua Titling MT" }, + { "perpetuatitlingmt", "Perpetua Titling MT" }, + { "plantagenet cherokee", "Plantagenet Cherokee" }, + { "plantagenetcherokee", "Plantagenet Cherokee" }, + { "playbill", "Playbill" }, + { "pmingliu", "PMingLiU" }, + { "pmingliu-extb", "PMingLiU-ExtB" }, + { "poor richard", "Poor Richard" }, + { "poorrichard", "Poor Richard" }, + { "pristina", "Pristina" }, + { "raavi", "Raavi" }, + { "rage italic", "Rage Italic" }, + { "rageitalic", "Rage Italic" }, + { "ravie", "Ravie" }, + { "rockwell", "Rockwell" }, + { "rockwell condensed", "Rockwell Condensed" }, + { "rockwell extra bold", "Rockwell Extra Bold" }, + { "rockwellcondensed", "Rockwell Condensed" }, + { "rockwellextrabold", "Rockwell Extra Bold" }, + { "rod", "Rod" }, + { "sakkal majalla", "Sakkal Majalla" }, + { "sakkalmajalla", "Sakkal Majalla" }, + { "script mt bold", "Script MT Bold" }, + { "scriptmtbold", "Script MT Bold" }, + { "segoe print", "Segoe Print" }, + { "segoe script", "Segoe Script" }, + { "segoe ui", "Segoe UI" }, + { "segoe ui light", "Segoe UI Light" }, + { "segoe ui semibold", "Segoe UI Semibold" }, + { "segoe ui symbol", "Segoe UI Symbol" }, + { "segoeprint", "Segoe Print" }, + { "segoescript", "Segoe Script" }, + { "segoeui", "Segoe UI" }, + { "segoeuilight", "Segoe UI Light" }, + { "segoeuisemibold", "Segoe UI Semibold" }, + { "segoeuisymbol", "Segoe UI Symbol" }, + { "shonar bangla", "Shonar Bangla" }, + { "shonarbangla", "Shonar Bangla" }, + { "showcard gothic", "Showcard Gothic" }, + { "showcardgothic", "Showcard Gothic" }, + { "shruti", "Shruti" }, + { "simhei", "SimHei" }, + { "simplified arabic", "Simplified Arabic" }, + { "simplified arabic fixed", "Simplified Arabic Fixed" }, + { "simplifiedarabic", "Simplified Arabic" }, + { "simplifiedarabicfixed", "Simplified Arabic Fixed" }, + { "simsun", "SimSun" }, + { "simsun-extb", "SimSun-ExtB" }, + { "snap itc", "Snap ITC" }, + { "snapitc", "Snap ITC" }, + { "stencil", "Stencil" }, + { "swgamekeys mt", "SWGamekeys MT" }, + { "swgamekeysmt", "SWGamekeys MT" }, + { "swmacro", "SWMacro" }, + { "sylfaen", "Sylfaen" }, + { "symbol", "Symbol" }, + { "tahoma", "Tahoma" }, + { "tempus sans itc", "Tempus Sans ITC" }, + { "tempussansitc", "Tempus Sans ITC" }, + { "times new roman", "Times New Roman" }, + { "timesnewroman", "Times New Roman" }, + { "traditional arabic", "Traditional Arabic" }, + { "traditionalarabic", "Traditional Arabic" }, + { "trebuchet ms", "Trebuchet MS" }, + { "trebuchetms", "Trebuchet MS" }, + { "tunga", "Tunga" }, + { "tw cen mt", "Tw Cen MT" }, + { "tw cen mt condensed", "Tw Cen MT Condensed" }, + { "tw cen mt condensed extra bold", "Tw Cen MT Condensed Extra Bold" }, + { "twcenmt", "Tw Cen MT" }, + { "twcenmtcondensed", "Tw Cen MT Condensed" }, + { "twcenmtcondensedextrabold", "Tw Cen MT Condensed Extra Bold" }, + { "utsaah", "Utsaah" }, + { "vani", "Vani" }, + { "verdana", "Verdana" }, + { "vijaya", "Vijaya" }, + { "viner hand itc", "Viner Hand ITC" }, + { "vinerhanditc", "Viner Hand ITC" }, + { "vivaldi", "Vivaldi" }, + { "vladimir script", "Vladimir Script" }, + { "vladimirscript", "Vladimir Script" }, + { "vrinda", "Vrinda" }, + { "webdings", "Webdings" }, + { "wide latin", "Wide Latin" }, + { "widelatin", "Wide Latin" }, + { "wingdings", "Wingdings" }, + { "wingdings 2", "Wingdings 2" }, + { "wingdings 3", "Wingdings 3" }, + { "wingdings2", "Wingdings 2" }, + { "wingdings3", "Wingdings 3" }, + }; private static TPoint? GetUsedSizeFromFontSizeProperty(CssExpression fontSize) { @@ -4044,15 +4334,16 @@ private static XElement GetBackgroundProperty(XElement element) if (color.ToString() != "transparent") { var hexString = color.ToString(); - var shd = new XElement(W.shd, + var shd = new XElement( + W.shd, new XAttribute(W.val, "clear"), new XAttribute(W.color, "auto"), - new XAttribute(W.fill, hexString)); + new XAttribute(W.fill, hexString) + ); return shd; } return null; } - } public class PictureId @@ -4062,17 +4353,23 @@ public class PictureId internal class HtmlToWmlFontUpdater { - public static void UpdateFontsPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings) + public static void UpdateFontsPart( + WordprocessingDocument wDoc, + XElement html, + HtmlToWmlConverterSettings settings + ) { var fontXDoc = wDoc.MainDocumentPart.FontTablePart.GetXDocument(); - PtUtils.AddElementIfMissing(fontXDoc, + PtUtils.AddElementIfMissing( + fontXDoc, fontXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1") + .Root.Elements(W.style) + .Where(e => + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1" + ) .FirstOrDefault(), -@" + @" @@ -4083,7 +4380,8 @@ public static void UpdateFontsPart(WordprocessingDocument wDoc, XElement html, H w:usb3='00000000' w:csb0='0000019F' w:csb1='00000000'/> -"); +" + ); wDoc.MainDocumentPart.FontTablePart.PutXDocument(); } @@ -4097,9 +4395,7 @@ public static void InitializeNumberingPart(WordprocessingDocument wDoc) if (numberingPart == null) { wDoc.MainDocumentPart.AddNewPart(); - var npXDoc = new XDocument( - new XElement(W.numbering, - new XAttribute(XNamespace.Xmlns + "w", W.w))); + var npXDoc = new XDocument(new XElement(W.numbering, new XAttribute(XNamespace.Xmlns + "w", W.w))); wDoc.MainDocumentPart.NumberingDefinitionsPart.PutXDocument(npXDoc); } } @@ -4109,12 +4405,17 @@ public static void GetNextNumId(WordprocessingDocument wDoc, out int nextNumId) InitializeNumberingPart(wDoc); var numberingPart = wDoc.MainDocumentPart.NumberingDefinitionsPart; var numberingXDoc = numberingPart.GetXDocument(); - nextNumId = numberingXDoc.Root.Elements(W.num).Attributes(W.numId).Select(ni => (int)ni).Concat(new[] { 1 }).Max(); + nextNumId = numberingXDoc + .Root.Elements(W.num) + .Attributes(W.numId) + .Select(ni => (int)ni) + .Concat(new[] { 1 }) + .Max(); } // decimal, lowerLetter private static readonly string OrderedListAbstractXml = -@" + @" @@ -4254,7 +4555,7 @@ public static void GetNextNumId(WordprocessingDocument wDoc, out int nextNumId) "; private static readonly string BulletAbstractXml = -@" + @" @@ -4403,14 +4704,30 @@ public static void GetNextNumId(WordprocessingDocument wDoc, out int nextNumId) "; - public static void UpdateNumberingPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings) + public static void UpdateNumberingPart( + WordprocessingDocument wDoc, + XElement html, + HtmlToWmlConverterSettings settings + ) { InitializeNumberingPart(wDoc); var numberingPart = wDoc.MainDocumentPart.NumberingDefinitionsPart; var numberingXDoc = numberingPart.GetXDocument(); - var nextNumId = numberingXDoc.Root.Elements(W.num).Attributes(W.numId).Select(ni => (int)ni).Concat(new[] { 1 }).Max(); - var nextAbstractId = numberingXDoc.Root.Elements(W.abstractNum).Attributes(W.abstractNumId).Select(ani => (int)ani).Concat(new[] { 0 }).Max(); - var numberingElements = html.DescendantsAndSelf().Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul).ToList(); + var nextNumId = numberingXDoc + .Root.Elements(W.num) + .Attributes(W.numId) + .Select(ni => (int)ni) + .Concat(new[] { 1 }) + .Max(); + var nextAbstractId = numberingXDoc + .Root.Elements(W.abstractNum) + .Attributes(W.abstractNumId) + .Select(ani => (int)ani) + .Concat(new[] { 0 }) + .Max(); + var numberingElements = html.DescendantsAndSelf() + .Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul) + .ToList(); var numToAbstractNum = new Dictionary(); @@ -4436,17 +4753,17 @@ public static void UpdateNumberingPart(WordprocessingDocument wDoc, XElement htm { numFmt[i] = "decimal"; just[i] = "left"; - var itemAtLevel = numberingElements - .FirstOrDefault(nf => - { - var n = nf.Annotation(); - if (n != null && n.numId == nia.numId && n.ilvl == i) - return true; - return false; - }); + var itemAtLevel = numberingElements.FirstOrDefault(nf => + { + var n = nf.Annotation(); + if (n != null && n.numId == nia.numId && n.ilvl == i) + return true; + return false; + }); if (itemAtLevel != null) { - var thisLevelNia = itemAtLevel.Annotation(); + var thisLevelNia = + itemAtLevel.Annotation(); var thisLevelNumFmt = thisLevelNia.listStyleType; if (thisLevelNumFmt is "lower-alpha" or "lower-latin") { @@ -4476,8 +4793,30 @@ public static void UpdateNumberingPart(WordprocessingDocument wDoc, XElement htm } } - var simpleNumAbstract = XElement.Parse(string.Format(OrderedListAbstractXml, currentAbstractId++, - numFmt[0], just[0], numFmt[1], just[1], numFmt[2], just[2], numFmt[3], just[3], numFmt[4], just[4], numFmt[5], just[5], numFmt[6], just[6], numFmt[7], just[7], numFmt[8], just[8])); + var simpleNumAbstract = XElement.Parse( + string.Format( + OrderedListAbstractXml, + currentAbstractId++, + numFmt[0], + just[0], + numFmt[1], + just[1], + numFmt[2], + just[2], + numFmt[3], + just[3], + numFmt[4], + just[4], + numFmt[5], + just[5], + numFmt[6], + just[6], + numFmt[7], + just[7], + numFmt[8], + just[8] + ) + ); numberingXDoc.Root.Add(simpleNumAbstract); } } @@ -4486,8 +4825,12 @@ public static void UpdateNumberingPart(WordprocessingDocument wDoc, XElement htm foreach (var list in numToAbstractNum) { numberingXDoc.Root.Add( - new XElement(W.num, new XAttribute(W.numId, list.Key), - new XElement(W.abstractNumId, new XAttribute(W.val, list.Value)))); + new XElement( + W.num, + new XAttribute(W.numId, list.Key), + new XElement(W.abstractNumId, new XAttribute(W.val, list.Value)) + ) + ); } wDoc.MainDocumentPart.NumberingDefinitionsPart.PutXDocument(); @@ -4507,20 +4850,28 @@ public static void UpdateStylesPart( HtmlToWmlConverterSettings settings, CssDocument defaultCssDoc, CssDocument authorCssDoc, - CssDocument userCssDoc) + CssDocument userCssDoc + ) { var styleXDoc = wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument(); if (settings.DefaultSpacingElement != null) { - var spacingElement = styleXDoc.Root.Elements(W.docDefaults).Elements(W.pPrDefault).Elements(W.pPr).Elements(W.spacing).FirstOrDefault(); + var spacingElement = styleXDoc + .Root.Elements(W.docDefaults) + .Elements(W.pPrDefault) + .Elements(W.pPr) + .Elements(W.spacing) + .FirstOrDefault(); if (spacingElement != null) spacingElement.ReplaceWith(settings.DefaultSpacingElement); } - var classes = html - .DescendantsAndSelf() - .Where(d => d.Attribute(XhtmlNoNamespace._class) != null && ((string)d.Attribute(XhtmlNoNamespace._class)).Split().Length == 1) + var classes = html.DescendantsAndSelf() + .Where(d => + d.Attribute(XhtmlNoNamespace._class) != null + && ((string)d.Attribute(XhtmlNoNamespace._class)).Split().Length == 1 + ) .Select(d => (string)d.Attribute(XhtmlNoNamespace._class)); foreach (var item in classes) @@ -4528,58 +4879,80 @@ public static void UpdateStylesPart( //string item = "ms-rteStyle-Byline"; foreach (var ruleSet in authorCssDoc.RuleSets) { - var selector = ruleSet.Selectors.Where( - sel => + var selector = ruleSet + .Selectors.Where(sel => { - var found = sel.SimpleSelectors.Count == 1 && - sel.SimpleSelectors.First().Class == item && - sel.SimpleSelectors.First().ElementName is "" or null; + var found = + sel.SimpleSelectors.Count == 1 + && sel.SimpleSelectors.First().Class == item + && sel.SimpleSelectors.First().ElementName is "" or null; return found; - }).FirstOrDefault(); + }) + .FirstOrDefault(); var color = ruleSet.Declarations.FirstOrDefault(d => d.Name == "color"); if (selector != null) { //Console.WriteLine("found ruleset and selector for {0}", item); var styleName = item.ToLower(); - var newStyle = new XElement(W.style, + var newStyle = new XElement( + W.style, new XAttribute(W.type, "paragraph"), new XAttribute(W.customStyle, "1"), new XAttribute(W.styleId, styleName), new XElement(W.name, new XAttribute(W.val, styleName)), new XElement(W.basedOn, new XAttribute(W.val, "Normal")), - new XElement(W.pPr, - new XElement(W.spacing, new XAttribute(W.before, "100"), + new XElement( + W.pPr, + new XElement( + W.spacing, + new XAttribute(W.before, "100"), new XAttribute(W.beforeAutospacing, "1"), new XAttribute(W.after, "100"), new XAttribute(W.afterAutospacing, "1"), new XAttribute(W.line, "240"), - new XAttribute(W.lineRule, "auto"))), - new XElement(W.rPr, - new XElement(W.rFonts, new XAttribute(W.ascii, "Times New Roman"), + new XAttribute(W.lineRule, "auto") + ) + ), + new XElement( + W.rPr, + new XElement( + W.rFonts, + new XAttribute(W.ascii, "Times New Roman"), new XAttribute(W.eastAsiaTheme, "minorEastAsia"), new XAttribute(W.hAnsi, "Times New Roman"), - new XAttribute(W.cs, "Times New Roman")), - color != null ? new XElement(W.color, new XAttribute(W.val, "this should be a color")) : null, + new XAttribute(W.cs, "Times New Roman") + ), + color != null + ? new XElement(W.color, new XAttribute(W.val, "this should be a color")) + : null, new XElement(W.sz, new XAttribute(W.val, "24")), - new XElement(W.szCs, new XAttribute(W.val, "24")))); - if (styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && ((string)e.Attribute(W.styleId)).ToLower() == styleName) - .FirstOrDefault() == null) + new XElement(W.szCs, new XAttribute(W.val, "24")) + ) + ); + if ( + styleXDoc + .Root.Elements(W.style) + .Where(e => + (string)e.Attribute(W.type) == "paragraph" + && ((string)e.Attribute(W.styleId)).ToLower() == styleName + ) + .FirstOrDefault() == null + ) styleXDoc.Root.Add(newStyle); } } } if (html.Descendants(XhtmlNoNamespace.h1).Any()) - PtUtils.AddElementIfMissing(styleXDoc, + PtUtils.AddElementIfMissing( + styleXDoc, styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1") + .Root.Elements(W.style) + .Where(e => + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1" + ) .FirstOrDefault(), -@" @@ -4608,16 +4981,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h2).Any()) - PtUtils.AddElementIfMissing(styleXDoc, + PtUtils.AddElementIfMissing( + styleXDoc, styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading2") + .Root.Elements(W.style) + .Where(e => + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading2" + ) .FirstOrDefault(), -@" @@ -4646,16 +5022,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h3).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading3") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading3" + ) + .FirstOrDefault(), + @" @@ -4682,16 +5061,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h4).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading4") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading4" + ) + .FirstOrDefault(), + @" @@ -4720,16 +5102,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h5).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading5") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading5" + ) + .FirstOrDefault(), + @" @@ -4755,16 +5140,19 @@ public static void UpdateStylesPart( w:themeColor='accent1' w:themeShade='7F'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h6).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading6") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading6" + ) + .FirstOrDefault(), + @" @@ -4792,16 +5180,19 @@ public static void UpdateStylesPart( w:themeColor='accent1' w:themeShade='7F'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h7).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading7") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading7" + ) + .FirstOrDefault(), + @" @@ -4829,16 +5220,19 @@ public static void UpdateStylesPart( w:themeColor='text1' w:themeTint='BF'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h8).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading8") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading8" + ) + .FirstOrDefault(), + @" @@ -4866,16 +5260,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h9).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading9") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading9" + ) + .FirstOrDefault(), + @" @@ -4905,16 +5302,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h1).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading1Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading1Char" + ) + .FirstOrDefault(), + @" @@ -4935,16 +5336,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h2).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading2Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading2Char" + ) + .FirstOrDefault(), + @" @@ -4964,16 +5369,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h3).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading3Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading3Char" + ) + .FirstOrDefault(), + @" @@ -4991,16 +5400,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h4).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading4Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading4Char" + ) + .FirstOrDefault(), + @" @@ -5020,16 +5433,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h5).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading5Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading5Char" + ) + .FirstOrDefault(), + @" @@ -5046,16 +5463,20 @@ public static void UpdateStylesPart( w:themeColor='accent1' w:themeShade='7F'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h6).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading6Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading6Char" + ) + .FirstOrDefault(), + @" @@ -5074,16 +5495,20 @@ public static void UpdateStylesPart( w:themeColor='accent1' w:themeShade='7F'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h7).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading7Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading7Char" + ) + .FirstOrDefault(), + @" @@ -5102,16 +5527,20 @@ public static void UpdateStylesPart( w:themeColor='text1' w:themeTint='BF'/> -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h8).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading8Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading8Char" + ) + .FirstOrDefault(), + @" @@ -5130,16 +5559,20 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.h9).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading9Char") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" + && (string)e.Attribute(W.styleId) == "Heading9Char" + ) + .FirstOrDefault(), + @" @@ -5160,16 +5593,19 @@ public static void UpdateStylesPart( -"); +" + ); if (html.Descendants(XhtmlNoNamespace.a).Any()) - PtUtils.AddElementIfMissing(styleXDoc, - styleXDoc - .Root - .Elements(W.style) - .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Hyperlink") - .FirstOrDefault(), -@" + (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Hyperlink" + ) + .FirstOrDefault(), + @" @@ -5181,7 +5617,8 @@ public static void UpdateStylesPart( -"); +" + ); wDoc.MainDocumentPart.StyleDefinitionsPart.PutXDocument(); } @@ -5189,28 +5626,34 @@ public static void UpdateStylesPart( internal class ThemeUpdater { - public static void UpdateThemePart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings) + public static void UpdateThemePart( + WordprocessingDocument wDoc, + XElement html, + HtmlToWmlConverterSettings settings + ) { var themeXDoc = wDoc.MainDocumentPart.ThemePart.GetXDocument(); var minorFont = html.Descendants(XhtmlNoNamespace.body).FirstOrDefault().GetProp("font-family"); - var majorFontElement = html.Descendants().Where(e => - e.Name == XhtmlNoNamespace.h1 || - e.Name == XhtmlNoNamespace.h2 || - e.Name == XhtmlNoNamespace.h3 || - e.Name == XhtmlNoNamespace.h4 || - e.Name == XhtmlNoNamespace.h5 || - e.Name == XhtmlNoNamespace.h6 || - e.Name == XhtmlNoNamespace.h7 || - e.Name == XhtmlNoNamespace.h8 || - e.Name == XhtmlNoNamespace.h9).FirstOrDefault(); + var majorFontElement = html.Descendants() + .Where(e => + e.Name == XhtmlNoNamespace.h1 + || e.Name == XhtmlNoNamespace.h2 + || e.Name == XhtmlNoNamespace.h3 + || e.Name == XhtmlNoNamespace.h4 + || e.Name == XhtmlNoNamespace.h5 + || e.Name == XhtmlNoNamespace.h6 + || e.Name == XhtmlNoNamespace.h7 + || e.Name == XhtmlNoNamespace.h8 + || e.Name == XhtmlNoNamespace.h9 + ) + .FirstOrDefault(); CssExpression majorFont = null; if (majorFontElement != null) majorFont = majorFontElement.GetProp("font-family"); var majorTypeface = themeXDoc - .Root - .Elements(A.themeElements) + .Root.Elements(A.themeElements) .Elements(A.fontScheme) .Elements(A.majorFont) .Elements(A.latin) @@ -5223,8 +5666,7 @@ public static void UpdateThemePart(WordprocessingDocument wDoc, XElement html, H majorTypeface.Value = term.Value; } var minorTypeface = themeXDoc - .Root - .Elements(A.themeElements) + .Root.Elements(A.themeElements) .Elements(A.fontScheme) .Elements(A.minorFont) .Elements(A.latin) diff --git a/Clippit/Html/HtmlToWmlCssApplier.cs b/Clippit/Html/HtmlToWmlCssApplier.cs index 2b0b6051..c6df9768 100644 --- a/Clippit/Html/HtmlToWmlCssApplier.cs +++ b/Clippit/Html/HtmlToWmlCssApplier.cs @@ -115,545 +115,777 @@ namespace Clippit.Html { internal class CssApplier { - private static readonly List PropertyInfoList = new() - { - // color - // Value: | inherit - // Initial: depends on UA - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "color" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "black", Type = CssTermType.String } } }, - ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List { new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String } } }, - }, - - // direction - // Value: ltr | rtl | inherit - // Initial: ltr - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "direction" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "ltr", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // line-height - // Value: normal | | | | - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: refer to the font size of the element itself - // Computed value: for and the absolute value, otherwise as specified. - new PropertyInfo + private static readonly List PropertyInfoList = + new() { - Names = new[] { "line-height" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }, - ComputedValue = (element, assignedValue, settings) => - { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element, "font-size", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + // color + // Value: | inherit + // Initial: depends on UA + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "color" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "black", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String }, + }, + }, }, - }, - - // visibility - // Value: visible | hidden | collapse | inherit - // Initial: visible - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "visibility" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "visible", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // list-style-type - // Value: disc | circle | square | decimal | decimal-leading-zero | - // lower-roman | upper-roman | lower-greek | lower-latin | - // upper-latin | armenian | georgian | lower-alpha | upper-alpha | - // none | inherit - // Initial: disc - // Applies to: elements with display: list-item - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "list-style-type" }, - Inherits = true, - Includes = (e, settings) => + // direction + // Value: ltr | rtl | inherit + // Initial: ltr + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "list-item") - return true; - return false; + Names = new[] { "direction" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "ltr", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "disc", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // list-style-image - // Value: | none | inherit - // Initial: none - // Applies to: elements with ’display: list-item’ - // Inherited: yes - // Percentages: N/A - // Computed value: absolute URI or ’none’ - new PropertyInfo - { - Names = new[] { "list-style-image" }, - Inherits = true, - Includes = (e, settings) => + // line-height + // Value: normal | | | | + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: refer to the font size of the element itself + // Computed value: for and the absolute value, otherwise as specified. + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "list-item") - return true; - return false; + Names = new[] { "line-height" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element, "font-size", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // list-style-position - // Value: inside | outside | inherit - // Initial: outside - // Applies to: elements with ’display: list-item’ - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "list-style-position" }, - Inherits = true, - Includes = (e, settings) => + // visibility + // Value: visible | hidden | collapse | inherit + // Initial: visible + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "list-item") - return true; - return false; + Names = new[] { "visibility" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "visible", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // font-family - // Value: [[ | ] [, | - // ]* ] | inherit - // Initial: depends on user agent - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "font-family" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = settings.MinorLatinFont, Type = CssTermType.String } } }, - ComputedValue = (element, assignedValue, settings) => assignedValue, - }, - - // font-style - // Value: normal | italic | oblique | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "font-style" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // font-variant - // Value: normal | small-caps | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "font-variant" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // font-weight - // Value: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | - // 600 | 700 | 800 | 900 | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: see text - new PropertyInfo - { - Names = new[] { "font-weight" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // font-size - // Value: | | | | - // inherit - // Initial: medium - // Applies to: all elements - // Inherited: yes - // Percentages: refer to inherited font size - // Computed value: absolute length - new PropertyInfo - { - Names = new[] { "font-size" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = settings.DefaultFontSize.ToString(CultureInfo.InvariantCulture), Type = CssTermType.String, Unit = CssUnit.PT } } }, - ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteFontSize(element, assignedValue, settings), - }, - - // text-indent - // Value: | | inherit - // Initial: 0 - // Applies to: block containers - // Inherited: yes - // Percentages: refer to width of containing block - // Computed value: the percentage as specified or the absolute length - new PropertyInfo - { - Names = new[] { "text-indent" }, - Inherits = true, - Includes = (e, settings) => + // list-style-type + // Value: disc | circle | square | decimal | decimal-leading-zero | + // lower-roman | upper-roman | lower-greek | lower-latin | + // upper-latin | armenian | georgian | lower-alpha | upper-alpha | + // none | inherit + // Initial: disc + // Applies to: elements with display: list-item + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "block") - return true; - return false; + Names = new[] { "list-style-type" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "list-item") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "disc", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + // list-style-image + // Value: | none | inherit + // Initial: none + // Applies to: elements with ’display: list-item’ + // Inherited: yes + // Percentages: N/A + // Computed value: absolute URI or ’none’ + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "list-style-image" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "list-item") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - }, - - // text-align - // Value: left | right | center | justify | inherit - // Initial: a nameless value that acts as ’left’ if ’direction’ is ’ltr’, ’right’ if - // ’direction’ is ’rtl’ - // Applies to: block containers - // Inherited: yes - // Percentages: N/A - // Computed value: the initial value or as spec - new PropertyInfo - { - Names = new[] { "text-align" }, - Inherits = true, - Includes = (e, settings) => + // list-style-position + // Value: inside | outside | inherit + // Initial: outside + // Applies to: elements with ’display: list-item’ + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "block") - return true; - return false; + Names = new[] { "list-style-position" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "list-item") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "left", Type = CssTermType.String, } } }, // todo should be based on the direction property - ComputedValue = null, - }, - - // text-decoration - // Value: none | [ underline || overline || line-through || blink ] | inherit - // Initial: none - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "text-decoration" }, - Inherits = true, // todo need to read css 16.3.1 in full detail to understand how this is implemented. - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // letter-spacing - // Value: normal | | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: ’normal’ or absolute length - - // word-spacing - // Value: normal | | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: for ’normal’ the value 0; otherwise the absolute length - new PropertyInfo - { - Names = new[] { "letter-spacing", "word-spacing" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String, } } }, - ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteLength(element, assignedValue, settings, null), - }, - - // white-space - // Value: normal | pre | nowrap | pre-wrap | pre-line | inherit - // Initial: normal - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "white-space" }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // caption-side - // Value: top | bottom | inherit - // Initial: top - // Applies to: 'table-caption' elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "caption-side" }, - Inherits = true, - Includes = (e, settings) => + // font-family + // Value: [[ | ] [, | + // ]* ] | inherit + // Initial: depends on user agent + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table-caption") - return true; - return false; + Names = new[] { "font-family" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = settings.MinorLatinFont, Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => assignedValue, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "top", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // border-collapse - // Value: collapse | separate | inherit - // Initial: separate - // Applies to: ’table’ and ’inline-table’ elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "border-collapse" }, - Inherits = true, - Includes = (e, settings) => + // font-style + // Value: normal | italic | oblique | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table" || display.ToString() == "inline-table") - return true; - return false; + Names = new[] { "font-style" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "separate", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // border-spacing - // Value: ? | inherit - // Initial: 0 - // Applies to: ’table’ and ’inline-table’ elements - // Inherited: yes - // Percentages: N/A - // Computed value: two absolute lengths - new PropertyInfo - { - Names = new[] { "border-spacing" }, - Inherits = true, - Includes = (e, settings) => + // font-variant + // Value: normal | small-caps | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table" || display.ToString() == "inline-table") - return true; - return false; + Names = new[] { "font-variant" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteLength(element, assignedValue, settings, null), // todo need to handle two lengths here - }, - - // empty-cells - // Value: show | hide | inherit - // Initial: show - // Applies to: 'table-cell' elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "empty-cells" }, - Inherits = true, - Includes = (e, settings) => + // font-weight + // Value: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | + // 600 | 700 | 800 | 900 | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: see text + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table" || display.ToString() == "table-cell") - return true; - return false; + Names = new[] { "font-weight" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "show", } } }, - ComputedValue = null, - }, - - // margin-top, margin-bottom - // Value: | inherit - // Initial: 0 - // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table - // all elements except th, td, tr - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage as specified or the absolute length - new PropertyInfo - { - Names = new[] { "margin-top", "margin-bottom", }, - Inherits = false, - Includes = (e, settings) => + // font-size + // Value: | | | | + // inherit + // Initial: medium + // Applies to: all elements + // Inherited: yes + // Percentages: refer to inherited font size + // Computed value: absolute length + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table-caption" || display.ToString() == "table" || display.ToString() == "inline-table") + Names = new[] { "font-size" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = settings.DefaultFontSize.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.String, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + ComputeAbsoluteFontSize(element, assignedValue, settings), + }, + // text-indent + // Value: | | inherit + // Initial: 0 + // Applies to: block containers + // Inherited: yes + // Percentages: refer to width of containing block + // Computed value: the percentage as specified or the absolute length + new PropertyInfo + { + Names = new[] { "text-indent" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "block") + return true; return false; - return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, + }, + // text-align + // Value: left | right | center | justify | inherit + // Initial: a nameless value that acts as ’left’ if ’direction’ is ’ltr’, ’right’ if + // ’direction’ is ’rtl’ + // Applies to: block containers + // Inherited: yes + // Percentages: N/A + // Computed value: the initial value or as spec + new PropertyInfo + { + Names = new[] { "text-align" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "block") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "left", Type = CssTermType.String }, + }, + }, // todo should be based on the direction property + ComputedValue = null, + }, + // text-decoration + // Value: none | [ underline || overline || line-through || blink ] | inherit + // Initial: none + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "text-decoration" }, + Inherits = true, // todo need to read css 16.3.1 in full detail to understand how this is implemented. + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, + }, + // letter-spacing + // Value: normal | | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: ’normal’ or absolute length + + // word-spacing + // Value: normal | | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: for ’normal’ the value 0; otherwise the absolute length + new PropertyInfo + { + Names = new[] { "letter-spacing", "word-spacing" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + ComputeAbsoluteLength(element, assignedValue, settings, null), + }, + // white-space + // Value: normal | pre | nowrap | pre-wrap | pre-line | inherit + // Initial: normal + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "white-space" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = null, + }, + // caption-side + // Value: top | bottom | inherit + // Initial: top + // Applies to: 'table-caption' elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "caption-side" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table-caption") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "top", Type = CssTermType.String }, + }, + }, + ComputedValue = null, + }, + // border-collapse + // Value: collapse | separate | inherit + // Initial: separate + // Applies to: ’table’ and ’inline-table’ elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "border-collapse" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table" || display.ToString() == "inline-table") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "separate", Type = CssTermType.String }, + }, + }, + ComputedValue = null, + }, + // border-spacing + // Value: ? | inherit + // Initial: 0 + // Applies to: ’table’ and ’inline-table’ elements + // Inherited: yes + // Percentages: N/A + // Computed value: two absolute lengths + new PropertyInfo + { + Names = new[] { "border-spacing" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table" || display.ToString() == "inline-table") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + ComputeAbsoluteLength(element, assignedValue, settings, null), // todo need to handle two lengths here }, - InitialValue = (element, settings) => + // empty-cells + // Value: show | hide | inherit + // Initial: show + // Applies to: 'table-cell' elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "empty-cells" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table" || display.ToString() == "table-cell") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression { Terms = new List { new() { Value = "show" } } }, + ComputedValue = null, + }, + // margin-top, margin-bottom + // Value: | inherit + // Initial: 0 + // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table + // all elements except th, td, tr + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage as specified or the absolute length + new PropertyInfo + { + Names = new[] { "margin-top", "margin-bottom" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if ( + display.ToString() == "table-caption" + || display.ToString() == "table" + || display.ToString() == "inline-table" + ) + return false; + return true; + }, + InitialValue = (element, settings) => { if (settings.DefaultBlockContentMargin != null) { if (settings.DefaultBlockContentMargin == "auto") - return new CssExpression { Terms = new List { new() { Value = "auto", Type = CssTermType.String } } }; + return new CssExpression + { + Terms = new List + { + new() { Value = "auto", Type = CssTermType.String }, + }, + }; else if (settings.DefaultBlockContentMargin.ToLower().EndsWith("pt")) { - var s1 = settings.DefaultBlockContentMargin.Substring(0, settings.DefaultBlockContentMargin.Length - 2); + var s1 = settings.DefaultBlockContentMargin.Substring( + 0, + settings.DefaultBlockContentMargin.Length - 2 + ); if (double.TryParse(s1, NumberStyles.Float, CultureInfo.InvariantCulture, out var d1)) { - return new CssExpression { Terms = new List { new() { Value = d1.ToString(CultureInfo.InvariantCulture), Type = CssTermType.Number, Unit = CssUnit.PT } } }; + return new CssExpression + { + Terms = new List + { + new() + { + Value = d1.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; } } throw new OpenXmlPowerToolsException("invalid setting"); } - return new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT } } }; + return new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); }, - ComputedValue = (element, assignedValue, settings) => - { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); - }, - }, - - // margin-right, margin-left - // Value: | inherit - // Initial: 0 - // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table - // all elements except th, td, tr - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage as specified or the absolute length - new PropertyInfo - { - Names = new[] { "margin-right", "margin-left", }, - Inherits = false, - Includes = (e, settings) => - { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table-caption" || display.ToString() == "table" || display.ToString() == "inline-table") - return false; - return true; }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + // margin-right, margin-left + // Value: | inherit + // Initial: 0 + // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table + // all elements except th, td, tr + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage as specified or the absolute length + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "margin-right", "margin-left" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if ( + display.ToString() == "table-caption" + || display.ToString() == "table" + || display.ToString() == "inline-table" + ) + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - }, - - // padding-top, padding-right, padding-bottom, padding-left - // Value: | inherit - // Initial: 0 - // Applies to: all elements except table-row-group, table-header-group, - // table-footer-group, table-row, table-column-group and table-column - // all elements except tr - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage as specified or the absolute length - new PropertyInfo - { - Names = new[] { "padding-top", "padding-right", "padding-bottom", "padding-left" }, - Inherits = false, - Includes = (e, settings) => + // padding-top, padding-right, padding-bottom, padding-left + // Value: | inherit + // Initial: 0 + // Applies to: all elements except table-row-group, table-header-group, + // table-footer-group, table-row, table-column-group and table-column + // all elements except tr + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage as specified or the absolute length + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "table-row-group" or "table-header-group" or "table-footer-group" or "table-row" or "table-column-group" or "table-column") - return false; - return true; + Names = new[] { "padding-top", "padding-right", "padding-bottom", "padding-left" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if ( + dv + is "table-row-group" + or "table-header-group" + or "table-footer-group" + or "table-row" + or "table-column-group" + or "table-column" + ) + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + // border-top-width, border-right-width, border-bottom-width, border-left-width + // Value: | inherit + // Initial: medium + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: absolute length; '0' if the border style is 'none' or 'hidden' + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); - }, - }, - - // border-top-width, border-right-width, border-bottom-width, border-left-width - // Value: | inherit - // Initial: medium - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: absolute length; '0' if the border style is 'none' or 'hidden' - new PropertyInfo - { - Names = new[] { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + Names = new[] + { + "border-top-width", + "border-right-width", + "border-bottom-width", + "border-left-width", + }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => { var assignedValueStr = assignedValue.ToString(); return assignedValueStr switch @@ -662,507 +894,673 @@ internal class CssApplier { Terms = new List { - new() { Value = "0.75", Type = CssTermType.Number, Unit = CssUnit.PT, } - } + new() + { + Value = "0.75", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, }, "medium" => new CssExpression { Terms = new List { - new() { Value = "3.0", Type = CssTermType.Number, Unit = CssUnit.PT, } - } + new() + { + Value = "3.0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, }, "thick" => new CssExpression { Terms = new List { - new() { Value = "4.5", Type = CssTermType.Number, Unit = CssUnit.PT, } - } + new() + { + Value = "4.5", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, }, - _ => ComputeAbsoluteLength(element, assignedValue, settings, null) + _ => ComputeAbsoluteLength(element, assignedValue, settings, null), }; }, - }, - - // border-top-style, border-right-style, border-bottom-style, border-left-style - // Value: | inherit - // Initial: none - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: as specified - new PropertyInfo - { - Names = new[] { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // display - // Value: inline | block | list-item | inline-block | table | inline-table | - // table-row-group | table-header-group | table-footer-group | - // table-row | table-column-group | table-column | table-cell | - // table-caption | none | inherit - // Initial: inline - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: see text - new PropertyInfo - { - Names = new[] { "display", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "inline", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // position - // Value: static | relative | absolute | fixed | inherit - // Initial: static - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: as specified - new PropertyInfo - { - Names = new[] { "position", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "static", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // float - // Value: left | right | none | inherit - // Initial: none - // Applies to: all, but see 9.7 p. 153 - // Inherited: no - // Percentages: N/A - // Computed value: as specified - new PropertyInfo - { - Names = new[] { "float", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // unicode-bidi - // Value: normal | embed | bidi-override | inherit - // Initial: normal - // Applies to: all elements, but see prose - // Inherited: no - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "unicode-bidi", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // background-color - // Value: | transparent | inherit - // Initial: transparent - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "background-color", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "transparent", Type = CssTermType.String } } }, - ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List { new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String } } }, - }, - - // text-transform - // Value: capitalize | uppercase | lowercase | none | inherit - // Initial: none - // Applies to: all elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "text-transform", }, - Inherits = true, - Includes = (e, settings) => true, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }, - ComputedValue = null, - }, - - // table-layout - // Value: auto | fixed | inherit - // Initial: auto - // Applies to: ’table’ and ’inline-table’ elements - // Inherited: no - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "table-layout" }, - Inherits = true, - Includes = (e, settings) => + }, + // border-top-style, border-right-style, border-bottom-style, border-left-style + // Value: | inherit + // Initial: none + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: as specified + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table" || display.ToString() == "inline-table") - return true; - return false; + Names = new[] + { + "border-top-style", + "border-right-style", + "border-bottom-style", + "border-left-style", + }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "auto", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // empty-cells - // Value: show | hide | inherit - // Initial: show - // Applies to: 'table-cell' elements - // Inherited: yes - // Percentages: N/A - // Computed value: as spec - new PropertyInfo - { - Names = new[] { "border-spacing" }, - Inherits = true, - Includes = (e, settings) => + // display + // Value: inline | block | list-item | inline-block | table | inline-table | + // table-row-group | table-header-group | table-footer-group | + // table-row | table-column-group | table-column | table-cell | + // table-caption | none | inherit + // Initial: inline + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: see text + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - if (display.ToString() == "table-cell") - return true; - return false; + Names = new[] { "display" }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "inline", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "show", Type = CssTermType.String, } } }, - ComputedValue = null, - }, - - // border-top-color, border-right-color, border-bottom-color, border-left-color - // Value: | transparent | inherit - // Initial: the value of the color property - // Applies to: all elements - // Inherited: no - // Percentages: N/A - // Computed value: when taken from the ’color’ property, the computed value of - // ’color’; otherwise, as specified - new PropertyInfo - { - Names = new[] { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", }, - Inherits = false, - Includes = (e, settings) => true, - InitialValue = (e, settings) => { - var display = GetComputedPropertyValue(null, e, "color", settings); - return display; + // position + // Value: static | relative | absolute | fixed | inherit + // Initial: static + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: as specified + new PropertyInfo + { + Names = new[] { "position" }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "static", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List { new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String } } }, - }, - - // width - // Value: | | auto | inherit - // Initial: auto - // Applies to: all elements but non-replaced in-line elements, table rows, and row groups - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage or 'auto' as specified or the absolute length - new PropertyInfo - { - Names = new[] { "width" }, - Inherits = false, - Includes = (e, settings) => + // float + // Value: left | right | none | inherit + // Initial: none + // Applies to: all, but see 9.7 p. 153 + // Inherited: no + // Percentages: N/A + // Computed value: as specified + new PropertyInfo { - if (e.Name == XhtmlNoNamespace.img) - return true; - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-row" or "table-row-group") - return false; - return true; + Names = new[] { "float" }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => - { - if (element.Parent == null) - { - var pageWidth = (double?)settings.SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault(); - if (pageWidth == null) - pageWidth = 12240; - var leftMargin = (double?)settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); - if (leftMargin == null) - leftMargin = 1440; - var rightMargin = (double?)settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); - if (rightMargin == null) - rightMargin = 1440; - var width = (double)(pageWidth - leftMargin - rightMargin) / 20; - return new CssExpression { Terms = new List { new() { Value = width.ToString(CultureInfo.InvariantCulture), Type = CssTermType.String, Unit = CssUnit.PT, } } }; - } - return new CssExpression { Terms = new List { new() { Value = "auto", Type = CssTermType.String, } } }; + // unicode-bidi + // Value: normal | embed | bidi-override | inherit + // Initial: normal + // Applies to: all elements, but see prose + // Inherited: no + // Percentages: N/A + // Computed value: as spec + new PropertyInfo + { + Names = new[] { "unicode-bidi" }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - ComputedValue = (element, assignedValue, settings) => + // background-color + // Value: | transparent | inherit + // Initial: transparent + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - if (element.Name != XhtmlNoNamespace.caption && - element.Name != XhtmlNoNamespace.td && - element.Name != XhtmlNoNamespace.th && - element.Name != XhtmlNoNamespace.tr && - element.Name != XhtmlNoNamespace.table && - assignedValue.IsAuto) - { - var pi = PropertyInfoList.FirstOrDefault(p => p.Names.Contains("width")); - var display = GetComputedPropertyValue(pi, element, "display", settings).ToString(); - if (display != "inline") + Names = new[] { "background-color" }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression { - var parentPropertyValue = GetComputedPropertyValue(pi, element.Parent, "width", settings); - return parentPropertyValue; - } - } - CssExpression valueForPercentage = null; - var elementToQuery = element.Parent; - while (elementToQuery != null) - { - valueForPercentage = GetComputedPropertyValue(null, elementToQuery, "width", settings); - if (valueForPercentage.IsAuto) + Terms = new List + { + new() { Value = "transparent", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + new CssExpression { - elementToQuery = elementToQuery.Parent; - continue; - } - break; - } - - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Terms = new List + { + new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String }, + }, + }, }, - }, - - // min-width - // Value: | | inherit - // Initial: 0 - // Applies to: all elements but non-replaced in-line elements, table rows, and row groups - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage as spec or the absolute length - new PropertyInfo - { - Names = new[] { "min-width" }, - Inherits = false, - Includes = (e, settings) => + // text-transform + // Value: capitalize | uppercase | lowercase | none | inherit + // Initial: none + // Applies to: all elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-row" or "table-row-group") - return false; - return true; + Names = new[] { "text-transform" }, + Inherits = true, + Includes = (e, settings) => true, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + // table-layout + // Value: auto | fixed | inherit + // Initial: auto + // Applies to: ’table’ and ’inline-table’ elements + // Inherited: no + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "table-layout" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table" || display.ToString() == "inline-table") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "auto", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - }, - - // max-width - // Value: | | none | inherit - // Initial: none - // Applies to: all elements but non-replaced in-line elements, table rows, and row groups - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: the percentage as spec or the absolute length - new PropertyInfo - { - Names = new[] { "max-width" }, - Inherits = false, - Includes = (e, settings) => + // empty-cells + // Value: show | hide | inherit + // Initial: show + // Applies to: 'table-cell' elements + // Inherited: yes + // Percentages: N/A + // Computed value: as spec + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-row" or "table-row-group") + Names = new[] { "border-spacing" }, + Inherits = true, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + if (display.ToString() == "table-cell") + return true; return false; - return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "show", Type = CssTermType.String }, + }, + }, + ComputedValue = null, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String, } } }, - ComputedValue = (element, assignedValue, settings) => + // border-top-color, border-right-color, border-bottom-color, border-left-color + // Value: | transparent | inherit + // Initial: the value of the color property + // Applies to: all elements + // Inherited: no + // Percentages: N/A + // Computed value: when taken from the ’color’ property, the computed value of + // ’color’; otherwise, as specified + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] + { + "border-top-color", + "border-right-color", + "border-bottom-color", + "border-left-color", + }, + Inherits = false, + Includes = (e, settings) => true, + InitialValue = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "color", settings); + return display; + }, + ComputedValue = (element, assignedValue, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = GetWmlColorFromExpression(assignedValue), Type = CssTermType.String }, + }, + }, }, - }, - - // height - // Value: | | auto | inherit - // Initial: auto - // Applies to: all elements but non-replaced in-line elements, table columns, and column groups - // Inherited: no - // Percentages: see prose - // Computed value: the percentage as spec or the absolute length - new PropertyInfo - { - Names = new[] { "height" }, - Inherits = false, - Includes = (e, settings) => + // width + // Value: | | auto | inherit + // Initial: auto + // Applies to: all elements but non-replaced in-line elements, table rows, and row groups + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage or 'auto' as specified or the absolute length + new PropertyInfo { - if (e.Name == XhtmlNoNamespace.img) + Names = new[] { "width" }, + Inherits = false, + Includes = (e, settings) => + { + if (e.Name == XhtmlNoNamespace.img) + return true; + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-row" or "table-row-group") + return false; return true; - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-row" or "table-row-group") - return false; - return true; + }, + InitialValue = (element, settings) => + { + if (element.Parent == null) + { + var pageWidth = (double?)settings.SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault(); + if (pageWidth == null) + pageWidth = 12240; + var leftMargin = (double?) + settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); + if (leftMargin == null) + leftMargin = 1440; + var rightMargin = (double?) + settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault(); + if (rightMargin == null) + rightMargin = 1440; + var width = (double)(pageWidth - leftMargin - rightMargin) / 20; + return new CssExpression + { + Terms = new List + { + new() + { + Value = width.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.String, + Unit = CssUnit.PT, + }, + }, + }; + } + return new CssExpression + { + Terms = new List + { + new() { Value = "auto", Type = CssTermType.String }, + }, + }; + }, + ComputedValue = (element, assignedValue, settings) => + { + if ( + element.Name != XhtmlNoNamespace.caption + && element.Name != XhtmlNoNamespace.td + && element.Name != XhtmlNoNamespace.th + && element.Name != XhtmlNoNamespace.tr + && element.Name != XhtmlNoNamespace.table + && assignedValue.IsAuto + ) + { + var pi = PropertyInfoList.FirstOrDefault(p => p.Names.Contains("width")); + var display = GetComputedPropertyValue(pi, element, "display", settings).ToString(); + if (display != "inline") + { + var parentPropertyValue = GetComputedPropertyValue( + pi, + element.Parent, + "width", + settings + ); + return parentPropertyValue; + } + } + CssExpression valueForPercentage = null; + var elementToQuery = element.Parent; + while (elementToQuery != null) + { + valueForPercentage = GetComputedPropertyValue(null, elementToQuery, "width", settings); + if (valueForPercentage.IsAuto) + { + elementToQuery = elementToQuery.Parent; + continue; + } + break; + } + + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "auto", Type = CssTermType.String, } } }, - ComputedValue = (element, assignedValue, settings) => + // min-width + // Value: | | inherit + // Initial: 0 + // Applies to: all elements but non-replaced in-line elements, table rows, and row groups + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage as spec or the absolute length + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "min-width" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-row" or "table-row-group") + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - }, - - // min-height - // Value: | | inherit - // Initial: 0 - // Applies to: all elements but non-replaced in-line elements, table columns, and column groups - // Inherited: no - // Percentages: see prose - // Computed value: the percentage as spec or the absolute length - new PropertyInfo - { - Names = new[] { "min-height" }, - Inherits = false, - Includes = (e, settings) => + // max-width + // Value: | | none | inherit + // Initial: none + // Applies to: all elements but non-replaced in-line elements, table rows, and row groups + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: the percentage as spec or the absolute length + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-column" or "table-column-group") - return false; - return true; + Names = new[] { "max-width" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-row" or "table-row-group") + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT, } } }, - ComputedValue = (element, assignedValue, settings) => + // height + // Value: | | auto | inherit + // Initial: auto + // Applies to: all elements but non-replaced in-line elements, table columns, and column groups + // Inherited: no + // Percentages: see prose + // Computed value: the percentage as spec or the absolute length + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "height" }, + Inherits = false, + Includes = (e, settings) => + { + if (e.Name == XhtmlNoNamespace.img) + return true; + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-row" or "table-row-group") + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "auto", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - }, - - // max-height - // Value: | | none | inherit - // Initial: none - // Applies to: all elements but non-replaced in-line elements, table columns, and column groups - // Inherited: no - // Percentages: refer to height of containing block - // Computed value: the percentage as spec or the absolute length - new PropertyInfo - { - Names = new[] { "max-height" }, - Inherits = false, - Includes = (e, settings) => + // min-height + // Value: | | inherit + // Initial: 0 + // Applies to: all elements but non-replaced in-line elements, table columns, and column groups + // Inherited: no + // Percentages: see prose + // Computed value: the percentage as spec or the absolute length + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-column" or "table-column-group") - return false; - return true; + Names = new[] { "min-height" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-column" or "table-column-group") + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String, } } }, - ComputedValue = (element, assignedValue, settings) => + // max-height + // Value: | | none | inherit + // Initial: none + // Applies to: all elements but non-replaced in-line elements, table columns, and column groups + // Inherited: no + // Percentages: refer to height of containing block + // Computed value: the percentage as spec or the absolute length + new PropertyInfo { - CssExpression valueForPercentage = null; - if (element.Parent != null) - valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); - return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + Names = new[] { "max-height" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-column" or "table-column-group") + return false; + return true; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => + { + CssExpression valueForPercentage = null; + if (element.Parent != null) + valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings); + return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage); + }, }, - }, - - // vertical-align - // Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | - // | | inherit - // Initial: baseline - // Applies to: inline-level and 'table-cell' elements - // Inherited: no - // Percentages: refer to the line height of the element itself - // Computed value: for and the absolute length, otherwise as specified. - new PropertyInfo - { - Names = new[] { "vertical-align" }, - Inherits = false, - Includes = (e, settings) => + // vertical-align + // Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | + // | | inherit + // Initial: baseline + // Applies to: inline-level and 'table-cell' elements + // Inherited: no + // Percentages: refer to the line height of the element itself + // Computed value: for and the absolute length, otherwise as specified. + new PropertyInfo { - var display = GetComputedPropertyValue(null, e, "display", settings); - var dv = display.ToString(); - if (dv is "inline" or "table-cell") - return true; - return false; + Names = new[] { "vertical-align" }, + Inherits = false, + Includes = (e, settings) => + { + var display = GetComputedPropertyValue(null, e, "display", settings); + var dv = display.ToString(); + if (dv is "inline" or "table-cell") + return true; + return false; + }, + InitialValue = (element, settings) => + new CssExpression + { + Terms = new List + { + new() { Value = "baseline", Type = CssTermType.String }, + }, + }, + ComputedValue = (element, assignedValue, settings) => assignedValue, // todo fix }, - InitialValue = (element, settings) => new CssExpression { Terms = new List { new() { Value = "baseline", Type = CssTermType.String, } } }, - ComputedValue = (element, assignedValue, settings) => assignedValue, // todo fix - }, - - // positioned elements are not supported - // - // top - // Value: | | auto | inherit - // Initial: auto - // Applies to: positioned elements - // Inherited: no - // Percentages: refer to height of containing block - // Computed value: if specified as a length, the corresponding absolute length; if - // specified as a percentage, the specified value; otherwise, ’auto’. - // - // right - // Value: | | auto | inherit - // Initial: auto - // Applies to: positioned elements - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: if specified as a length, the corresponding absolute length; if - // specified as a percentage, the specified value; otherwise, ’auto’. - // - // bottom - // Value: | | auto | inherit - // Initial: auto - // Applies to: positioned elements - // Inherited: no - // Percentages: refer to height of containing block - // Computed value: if specified as a length, the corresponding absolute length; if - // specified as a percentage, the specified value; otherwise, ’auto’. - // - // left - // Value: | | auto | inherit - // Initial: auto - // Applies to: positioned elements - // Inherited: no - // Percentages: refer to width of containing block - // Computed value: if specified as a length, the corresponding absolute length; if - // specified as a percentage, the specified value; otherwise, ’auto’. - - // floated elements are not supported - // - // clear - // Value: none | left | right | both | inherit - // Initial: none - // Applies to: block-level elements - // Inherited: no - // Percentages: N/A - // Computed value: as specified - // - // z-index - // Value: auto | integer | inherit - // Initial: auto - // Applies to: positioned elements - // Inherited: no - // Percentages: N/A - // Computed value: as spec - }; + + // positioned elements are not supported + // + // top + // Value: | | auto | inherit + // Initial: auto + // Applies to: positioned elements + // Inherited: no + // Percentages: refer to height of containing block + // Computed value: if specified as a length, the corresponding absolute length; if + // specified as a percentage, the specified value; otherwise, ’auto’. + // + // right + // Value: | | auto | inherit + // Initial: auto + // Applies to: positioned elements + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: if specified as a length, the corresponding absolute length; if + // specified as a percentage, the specified value; otherwise, ’auto’. + // + // bottom + // Value: | | auto | inherit + // Initial: auto + // Applies to: positioned elements + // Inherited: no + // Percentages: refer to height of containing block + // Computed value: if specified as a length, the corresponding absolute length; if + // specified as a percentage, the specified value; otherwise, ’auto’. + // + // left + // Value: | | auto | inherit + // Initial: auto + // Applies to: positioned elements + // Inherited: no + // Percentages: refer to width of containing block + // Computed value: if specified as a length, the corresponding absolute length; if + // specified as a percentage, the specified value; otherwise, ’auto’. + + // floated elements are not supported + // + // clear + // Value: none | left | right | both | inherit + // Initial: none + // Applies to: block-level elements + // Inherited: no + // Percentages: N/A + // Computed value: as specified + // + // z-index + // Value: auto | integer | inherit + // Initial: auto + // Applies to: positioned elements + // Inherited: no + // Percentages: N/A + // Computed value: as spec + }; /* * 1. Process user-agent default style sheet @@ -1183,7 +1581,8 @@ public static void ApplyAllCss( out CssDocument defaultCssDoc, out CssDocument authorCssDoc, out CssDocument userCssDoc, - string annotatedHtmlDumpFileName) + string annotatedHtmlDumpFileName + ) { var propertySequence = 1; @@ -1194,7 +1593,8 @@ public static void ApplyAllCss( newXHtml, Property.HighOrderPriority.UserAgentNormal, Property.HighOrderPriority.UserAgentHigh, - ref propertySequence); + ref propertySequence + ); //// todo dump here, see if margin is set on body. //if (annotatedHtmlDumpFileName != null) @@ -1215,7 +1615,8 @@ public static void ApplyAllCss( newXHtml, Property.HighOrderPriority.UserHigh, Property.HighOrderPriority.UserNormal, - ref propertySequence); + ref propertySequence + ); //DumpCss(userCssDoc); //Environment.Exit(0); @@ -1227,7 +1628,8 @@ public static void ApplyAllCss( newXHtml, Property.HighOrderPriority.AuthorNormal, Property.HighOrderPriority.AuthorHigh, - ref propertySequence); + ref propertySequence + ); //string s = DumpCss(authorCssDoc); //File.WriteAllText("CssTreeDump.txt", s); @@ -1284,8 +1686,12 @@ compute value set the computed value return the computed value #endif - public static CssExpression GetComputedPropertyValue(PropertyInfo propertyInfo, XElement element, string propertyName, - HtmlToWmlConverterSettings settings) + public static CssExpression GetComputedPropertyValue( + PropertyInfo propertyInfo, + XElement element, + string propertyName, + HtmlToWmlConverterSettings settings + ) { // if (property is already computed) // return the computed value @@ -1312,19 +1718,40 @@ public static CssExpression GetComputedPropertyValue(PropertyInfo propertyInfo, var propList = element.Annotation>(); if (propList == null) { - var computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, false, settings); + var computedValue = GetInheritedOrInitializedValue( + computedValues, + propertyInfo, + element, + propertyName, + false, + settings + ); return computedValue; } if (!propList.ContainsKey(pName)) { - var computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, false, settings); + var computedValue = GetInheritedOrInitializedValue( + computedValues, + propertyInfo, + element, + propertyName, + false, + settings + ); return computedValue; } var prop = propList[pName]; var propStr = prop.Expression.ToString(); if (propStr is "inherited" or "auto") { - var computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, true, settings); + var computedValue = GetInheritedOrInitializedValue( + computedValues, + propertyInfo, + element, + propertyName, + true, + settings + ); return computedValue; } // if property is set, then compute the value, return the computed value @@ -1348,11 +1775,27 @@ public static CssExpression GetComputedPropertyValue(PropertyInfo propertyInfo, // compute value // set the computed value // return the computed value - public static CssExpression GetInheritedOrInitializedValue(Dictionary computedValues, PropertyInfo propertyInfo, XElement element, string propertyName, bool valueIsInherit, HtmlToWmlConverterSettings settings) + public static CssExpression GetInheritedOrInitializedValue( + Dictionary computedValues, + PropertyInfo propertyInfo, + XElement element, + string propertyName, + bool valueIsInherit, + HtmlToWmlConverterSettings settings + ) { - if ((propertyInfo.Inherits || valueIsInherit) && element.Parent != null && propertyInfo.Includes(element.Parent, settings)) + if ( + (propertyInfo.Inherits || valueIsInherit) + && element.Parent != null + && propertyInfo.Includes(element.Parent, settings) + ) { - var parentPropertyValue = GetComputedPropertyValue(propertyInfo, element.Parent, propertyName, settings); + var parentPropertyValue = GetComputedPropertyValue( + propertyInfo, + element.Parent, + propertyName, + settings + ); computedValues.Add(propertyName, parentPropertyValue); return parentPropertyValue; } @@ -1371,20 +1814,31 @@ private static void ApplyCssDocument( XElement xHtml, Property.HighOrderPriority notImportantHighOrderSort, Property.HighOrderPriority importantHighOrderSort, - ref int propertySequence) + ref int propertySequence + ) { foreach (var ruleSet in cssDoc.RuleSets) { foreach (var selector in ruleSet.Selectors) { - ApplySelector(selector, ruleSet, xHtml, notImportantHighOrderSort, - importantHighOrderSort, ref propertySequence); + ApplySelector( + selector, + ruleSet, + xHtml, + notImportantHighOrderSort, + importantHighOrderSort, + ref propertySequence + ); } } } - private static CssExpression ComputeAbsoluteLength(XElement element, CssExpression assignedValue, HtmlToWmlConverterSettings settings, - CssExpression lengthForPercentage) + private static CssExpression ComputeAbsoluteLength( + XElement element, + CssExpression assignedValue, + HtmlToWmlConverterSettings settings, + CssExpression lengthForPercentage + ) { if (assignedValue.Terms.Count != 1) throw new OpenXmlPowerToolsException("Should not have a unit with more than one term"); @@ -1394,17 +1848,50 @@ private static CssExpression ComputeAbsoluteLength(XElement element, CssExpressi if (value == "thin") { - var newExpr1 = new CssExpression { Terms = new List { new() { Value = ".3", Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + var newExpr1 = new CssExpression + { + Terms = new List + { + new() + { + Value = ".3", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; return newExpr1; } if (value == "medium") { - var newExpr2 = new CssExpression { Terms = new List { new() { Value = "1.20", Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + var newExpr2 = new CssExpression + { + Terms = new List + { + new() + { + Value = "1.20", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; return newExpr2; } if (value == "thick") { - var newExpr3 = new CssExpression { Terms = new List { new() { Value = "1.80", Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + var newExpr3 = new CssExpression + { + Terms = new List + { + new() + { + Value = "1.80", + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; return newExpr3; } if (value is "auto" or "normal" or "none") @@ -1415,7 +1902,13 @@ private static CssExpression ComputeAbsoluteLength(XElement element, CssExpressi return assignedValue; if (unit == CssUnit.Percent && lengthForPercentage == null) - return new CssExpression { Terms = new List { new() { Value = "auto", Type = CssTermType.String } } }; + return new CssExpression + { + Terms = new List + { + new() { Value = "auto", Type = CssTermType.String }, + }, + }; if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var decValue)) throw new OpenXmlPowerToolsException("value did not parse"); @@ -1425,14 +1918,28 @@ private static CssExpression ComputeAbsoluteLength(XElement element, CssExpressi double? newPtSize = null; if (unit == CssUnit.Percent) { - if (!double.TryParse(lengthForPercentage.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var ptSize)) + if ( + !double.TryParse( + lengthForPercentage.Terms.First().Value, + NumberStyles.Float, + CultureInfo.InvariantCulture, + out var ptSize + ) + ) throw new OpenXmlPowerToolsException("did not return a double?"); newPtSize = ptSize * decValue / 100d; } else if (unit is CssUnit.EM or CssUnit.EX) { var fontSize = GetComputedPropertyValue(null, element, "font-size", settings); - if (!double.TryParse(fontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var decFontSize)) + if ( + !double.TryParse( + fontSize.Terms.First().Value, + NumberStyles.Float, + CultureInfo.InvariantCulture, + out var decFontSize + ) + ) throw new OpenXmlPowerToolsException("Internal error"); newPtSize = (unit == CssUnit.EM) ? decFontSize * decValue : decFontSize * decValue / 2; } @@ -1450,16 +1957,31 @@ private static CssExpression ComputeAbsoluteLength(XElement element, CssExpressi CssUnit.MM => (decValue / 25.4d) * 72.0d, CssUnit.PC => decValue * 12d, CssUnit.PX => decValue * 0.75d, - _ => newPtSize + _ => newPtSize, }; } if (!newPtSize.HasValue) throw new OpenXmlPowerToolsException("Internal error: should not have reached this exception"); - var newExpr = new CssExpression { Terms = new List { new() { Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + var newExpr = new CssExpression + { + Terms = new List + { + new() + { + Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; return newExpr; } - private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpression assignedValue, HtmlToWmlConverterSettings settings) + private static CssExpression ComputeAbsoluteFontSize( + XElement element, + CssExpression assignedValue, + HtmlToWmlConverterSettings settings + ) { if (assignedValue.Terms.Count != 1) throw new OpenXmlPowerToolsException("Should not have a unit with more than one term, I think"); @@ -1468,13 +1990,31 @@ private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpres if (unit == CssUnit.PT) return assignedValue; if (FontSizeMap.ContainsKey(value)) - return new CssExpression { Terms = new List { new() { Value = FontSizeMap[value].ToString(CultureInfo.InvariantCulture), Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + return new CssExpression + { + Terms = new List + { + new() + { + Value = FontSizeMap[value].ToString(CultureInfo.InvariantCulture), + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; // todo what should the calculation be for computing larger / smaller? if (value is "larger" or "smaller") { var parentFontSize = GetComputedPropertyValue(null, element.Parent, "font-size", settings); - if (!double.TryParse(parentFontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var ptSize)) + if ( + !double.TryParse( + parentFontSize.Terms.First().Value, + NumberStyles.Float, + CultureInfo.InvariantCulture, + out var ptSize + ) + ) throw new OpenXmlPowerToolsException("did not return a double?"); double newPtSize2 = 0; if (value == "larger") @@ -1487,7 +2027,7 @@ private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpres >= 13 and <= 15 => 18d, >= 16 and <= 20 => 24d, >= 21 => 36d, - _ => newPtSize2 + _ => newPtSize2, }; } if (value == "smaller") @@ -1500,10 +2040,21 @@ private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpres >= 16 and <= 20 => 13.5d, >= 21 and <= 29 => 18d, >= 30 => 24d, - _ => newPtSize2 + _ => newPtSize2, }; } - return new CssExpression { Terms = new List { new() { Value = newPtSize2.ToString(CultureInfo.InvariantCulture), Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + return new CssExpression + { + Terms = new List + { + new() + { + Value = newPtSize2.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; } if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var decValue)) @@ -1512,14 +2063,21 @@ private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpres if (unit is CssUnit.EM or CssUnit.EX or CssUnit.Percent) { var parentFontSize = GetComputedPropertyValue(null, element.Parent, "font-size", settings); - if (!double.TryParse(parentFontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var ptSize)) + if ( + !double.TryParse( + parentFontSize.Terms.First().Value, + NumberStyles.Float, + CultureInfo.InvariantCulture, + out var ptSize + ) + ) throw new OpenXmlPowerToolsException("did not return a double?"); newPtSize = unit switch { CssUnit.EM => ptSize * decValue, CssUnit.EX => ptSize / 2 * decValue, CssUnit.Percent => ptSize * decValue / 100d, - _ => newPtSize + _ => newPtSize, }; } else if (unit == CssUnit.REM) @@ -1535,25 +2093,37 @@ private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpres CssUnit.MM => (decValue / 25.4d) * 72.0d, CssUnit.PC => decValue * 12d, CssUnit.PX => decValue * 0.75d, - _ => newPtSize + _ => newPtSize, }; } if (!newPtSize.HasValue) throw new OpenXmlPowerToolsException("Internal error: should not have reached this exception"); - var newExpr = new CssExpression { Terms = new List { new() { Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), Type = CssTermType.Number, Unit = CssUnit.PT, } } }; + var newExpr = new CssExpression + { + Terms = new List + { + new() + { + Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), + Type = CssTermType.Number, + Unit = CssUnit.PT, + }, + }, + }; return newExpr; } - private static readonly Dictionary FontSizeMap = new() - { - { "xx-small", 7.5d }, - { "x-small", 10d }, - { "small", 12d }, - { "medium", 13.5d }, - { "large", 18d }, - { "x-large", 24d }, - { "xx-large", 36d }, - }; + private static readonly Dictionary FontSizeMap = + new() + { + { "xx-small", 7.5d }, + { "x-small", 10d }, + { "small", 12d }, + { "medium", 13.5d }, + { "large", 18d }, + { "x-large", 24d }, + { "xx-large", 36d }, + }; private static void ApplySelector( CssSelector selector, @@ -1561,7 +2131,8 @@ private static void ApplySelector( XElement xHtml, Property.HighOrderPriority notImportantHighOrderSort, Property.HighOrderPriority importantHighOrderSort, - ref int propertySequence) + ref int propertySequence + ) { foreach (var element in xHtml.DescendantsAndSelf()) { @@ -1585,9 +2156,7 @@ private static void ApplySelector( } } - private static bool DoesSelectorMatch( - CssSelector selector, - XElement element) + private static bool DoesSelectorMatch(CssSelector selector, XElement element) { var currentSimpleSelector = selector.SimpleSelectors.Count - 1; var currentElement = element; @@ -1633,9 +2202,7 @@ private static bool DoesSelectorMatch( } } - private static bool DoesSimpleSelectorMatch( - CssSimpleSelector simpleSelector, - XElement element) + private static bool DoesSimpleSelectorMatch(CssSimpleSelector simpleSelector, XElement element) { var elemantNameMatch = true; var classNameMatch = true; @@ -1645,7 +2212,11 @@ private static bool DoesSimpleSelectorMatch( if (simpleSelector.Pseudo != null) return false; - if (simpleSelector.ElementName != null && simpleSelector.ElementName != "" && simpleSelector.ElementName != "*") + if ( + simpleSelector.ElementName != null + && simpleSelector.ElementName != "" + && simpleSelector.ElementName != "*" + ) elemantNameMatch = element.Name.ToString() == simpleSelector.ElementName; if (elemantNameMatch) { @@ -1672,12 +2243,7 @@ private static bool DoesSimpleSelectorMatch( } } } - var result = - elemantNameMatch && - classNameMatch && - childSimpleSelectorMatch && - idMatch && - attributeMatch; + var result = elemantNameMatch && classNameMatch && childSimpleSelectorMatch && idMatch && attributeMatch; return result; } @@ -1698,14 +2264,16 @@ private static bool DoesAttributeMatch(CssAttribute attribute, XElement element) CssAttributeOperator.EndsWith => attValue.EndsWith(value), CssAttributeOperator.InList => attValue.Split(' ').Contains(value), CssAttributeOperator.Hyphenated => attValue.Split('-')[0] == value, - _ => false + _ => false, }; } private static int CountIdAttributesInSimpleSelector(CssSimpleSelector simpleSelector) { - var count = simpleSelector.ID != null ? 1 : 0 + - (simpleSelector.Child != null ? CountIdAttributesInSimpleSelector(simpleSelector.Child) : 0); + var count = + simpleSelector.ID != null + ? 1 + : 0 + (simpleSelector.Child != null ? CountIdAttributesInSimpleSelector(simpleSelector.Child) : 0); return count; } @@ -1717,9 +2285,10 @@ private static int CountIdAttributesInSelector(CssSelector selector) private static int CountAttributesInSimpleSelector(CssSimpleSelector simpleSelector) { - var count = (simpleSelector.Attribute != null ? 1 : 0) + - ((simpleSelector.Class != null && simpleSelector.Class != "") ? 1 : 0) + - (simpleSelector.Child != null ? CountAttributesInSimpleSelector(simpleSelector.Child) : 0); + var count = + (simpleSelector.Attribute != null ? 1 : 0) + + ((simpleSelector.Class != null && simpleSelector.Class != "") ? 1 : 0) + + (simpleSelector.Child != null ? CountAttributesInSimpleSelector(simpleSelector.Child) : 0); return count; } @@ -1731,11 +2300,14 @@ private static int CountAttributesInSelector(CssSelector selector) private static int CountElementNamesInSimpleSelector(CssSimpleSelector simpleSelector) { - var count = (simpleSelector.ElementName != null && - simpleSelector.ElementName != "" && - simpleSelector.ElementName != "*") - ? 1 : 0 + - (simpleSelector.Child != null ? CountElementNamesInSimpleSelector(simpleSelector.Child) : 0); + var count = + ( + simpleSelector.ElementName != null + && simpleSelector.ElementName != "" + && simpleSelector.ElementName != "*" + ) + ? 1 + : 0 + (simpleSelector.Child != null ? CountElementNamesInSimpleSelector(simpleSelector.Child) : 0); return count; } @@ -1745,9 +2317,7 @@ private static int CountElementNamesInSelector(CssSelector selector) return count; } - private static void AddPropertyToElement( - XElement element, - Property property) + private static void AddPropertyToElement(XElement element, Property property) { //if (property.Name == "direction") // Console.WriteLine(1); @@ -1767,9 +2337,7 @@ private static void AddPropertyToElement( } } - private static void AddPropertyToDictionary( - Dictionary propList, - Property property) + private static void AddPropertyToDictionary(Dictionary propList, Property property) { if (!propList.ContainsKey(property.Name)) propList.Add(property.Name, property); @@ -1794,7 +2362,8 @@ private static void ApplyDeclarationsToElement( XElement element, Property.HighOrderPriority notImportantHighOrderSort, Property.HighOrderPriority importantHighOrderSort, - ref int propertySequence) + ref int propertySequence + ) { foreach (var declaration in ruleSet.Declarations) { @@ -1817,11 +2386,18 @@ private static void ApplyCssToElement( XElement element, Property.HighOrderPriority notImportantHighOrderSort, Property.HighOrderPriority importantHighOrderSort, - ref int propertySequence) + ref int propertySequence + ) { foreach (var ruleSet in cssDoc.RuleSets) { - ApplyDeclarationsToElement(ruleSet, element, notImportantHighOrderSort, importantHighOrderSort, ref propertySequence); + ApplyDeclarationsToElement( + ruleSet, + element, + notImportantHighOrderSort, + importantHighOrderSort, + ref propertySequence + ); } } @@ -1842,7 +2418,8 @@ private static void ApplyStyleAttributes(XElement xHtml, ref int propertySequenc element, Property.HighOrderPriority.StyleAttributeNormal, Property.HighOrderPriority.StyleAttributeHigh, - ref propertySequence); + ref propertySequence + ); } var dirAtt = element.Attribute(XhtmlNoNamespace.dir); if (dirAtt != null) @@ -1851,7 +2428,13 @@ private static void ApplyStyleAttributes(XElement xHtml, ref int propertySequenc var prop = new Property() { Name = "direction", - Expression = new CssExpression { Terms = new List { new() { Value = dir, Type = CssTermType.String } } }, + Expression = new CssExpression + { + Terms = new List + { + new() { Value = dir, Type = CssTermType.String }, + }, + }, HighOrderSort = Property.HighOrderPriority.HtmlAttribute, IdAttributesInSelector = 0, AttributesInSelector = 0, @@ -1893,31 +2476,11 @@ private class ShorthandPropertiesInfo private static readonly ShorthandPropertiesInfo[] ShorthandProperties = new[] { - new ShorthandPropertiesInfo - { - Name = "margin", - Pattern = "margin-{0}", - }, - new ShorthandPropertiesInfo - { - Name = "padding", - Pattern = "padding-{0}", - }, - new ShorthandPropertiesInfo - { - Name = "border-width", - Pattern = "border-{0}-width", - }, - new ShorthandPropertiesInfo - { - Name = "border-color", - Pattern = "border-{0}-color", - }, - new ShorthandPropertiesInfo - { - Name = "border-style", - Pattern = "border-{0}-style", - }, + new ShorthandPropertiesInfo { Name = "margin", Pattern = "margin-{0}" }, + new ShorthandPropertiesInfo { Name = "padding", Pattern = "padding-{0}" }, + new ShorthandPropertiesInfo { Name = "border-width", Pattern = "border-{0}-width" }, + new ShorthandPropertiesInfo { Name = "border-color", Pattern = "border-{0}-color" }, + new ShorthandPropertiesInfo { Name = "border-style", Pattern = "border-{0}-style" }, }; private static void ExpandShorthandProperties(XElement xHtml, HtmlToWmlConverterSettings settings) @@ -1946,9 +2509,27 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo CssExpression borderStyle; if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit") { - borderColor = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - borderWidth = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - borderStyle = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; + borderColor = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + borderWidth = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + borderStyle = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; } else { @@ -2029,9 +2610,27 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo CssExpression borderStyle; if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit") { - borderColor = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - borderWidth = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - borderStyle = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; + borderColor = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + borderWidth = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + borderStyle = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; } else { @@ -2110,15 +2709,51 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo CssExpression listStyleImage; if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit") { - listStyleType = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - listStylePosition = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - listStyleImage = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; + listStyleType = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + listStylePosition = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + listStyleImage = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; } else { - listStyleType = new CssExpression { Terms = new List { new() { Value = "disc", Type = CssTermType.String } } }; - listStylePosition = new CssExpression { Terms = new List { new() { Value = "outside", Type = CssTermType.String } } }; - listStyleImage = new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }; + listStyleType = new CssExpression + { + Terms = new List + { + new() { Value = "disc", Type = CssTermType.String }, + }, + }; + listStylePosition = new CssExpression + { + Terms = new List + { + new() { Value = "outside", Type = CssTermType.String }, + }, + }; + listStyleImage = new CssExpression + { + Terms = new List + { + new() { Value = "none", Type = CssTermType.String }, + }, + }; foreach (var term in p.Expression.Terms) { var dataType = GetDatatypeFromListStyleTerm(term); @@ -2181,32 +2816,89 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo CssExpression backgroundPosition; if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit") { - backgroundColor = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - backgroundImage = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - backgroundRepeat = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - backgroundAttachment = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - backgroundPosition = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; + backgroundColor = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + backgroundImage = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + backgroundRepeat = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + backgroundAttachment = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + backgroundPosition = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; } else { - backgroundColor = new CssExpression { Terms = new List { new() { Value = "transparent", Type = CssTermType.String } } }; - backgroundImage = new CssExpression { Terms = new List { new() { Value = "none", Type = CssTermType.String } } }; - backgroundRepeat = new CssExpression { Terms = new List { new() { Value = "repeat", Type = CssTermType.String } } }; - backgroundAttachment = new CssExpression { Terms = new List { new() { Value = "scroll", Type = CssTermType.String } } }; - backgroundPosition = new CssExpression + backgroundColor = new CssExpression { - Terms = new List { - new() + Terms = new List { - Value = "0", - Unit = CssUnit.Percent, - Type = CssTermType.Number }, - new() + new() { Value = "transparent", Type = CssTermType.String }, + }, + }; + backgroundImage = new CssExpression + { + Terms = new List { - Value = "0", - Unit = CssUnit.Percent, - Type = CssTermType.Number }, - } + new() { Value = "none", Type = CssTermType.String }, + }, + }; + backgroundRepeat = new CssExpression + { + Terms = new List + { + new() { Value = "repeat", Type = CssTermType.String }, + }, + }; + backgroundAttachment = new CssExpression + { + Terms = new List + { + new() { Value = "scroll", Type = CssTermType.String }, + }, + }; + backgroundPosition = new CssExpression + { + Terms = new List + { + new() + { + Value = "0", + Unit = CssUnit.Percent, + Type = CssTermType.Number, + }, + new() + { + Value = "0", + Unit = CssUnit.Percent, + Type = CssTermType.Number, + }, + }, }; var backgroundPositionList = new List(); foreach (var term in p.Expression.Terms) @@ -2240,10 +2932,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo { backgroundPositionList.First(), new() { Value = "center", Type = CssTermType.String }, - } + }, }, 2 => new CssExpression { Terms = backgroundPositionList }, - _ => backgroundPosition + _ => backgroundPosition, }; } var bc = new Property @@ -2314,21 +3006,93 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo CssExpression fontFamily; if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit") { - fontStyle = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - fontVarient = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - fontWeight = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - fontSize = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - lineHeight = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; - fontFamily = new CssExpression { Terms = new List { new() { Value = "inherit", Type = CssTermType.String } } }; + fontStyle = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + fontVarient = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + fontWeight = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + fontSize = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + lineHeight = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; + fontFamily = new CssExpression + { + Terms = new List + { + new() { Value = "inherit", Type = CssTermType.String }, + }, + }; } else { - fontStyle = new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }; - fontVarient = new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }; - fontWeight = new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }; - fontSize = new CssExpression { Terms = new List { new() { Value = "medium", Type = CssTermType.String } } }; - lineHeight = new CssExpression { Terms = new List { new() { Value = "normal", Type = CssTermType.String } } }; - fontFamily = new CssExpression { Terms = new List { new() { Value = "serif", Type = CssTermType.String } } }; + fontStyle = new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }; + fontVarient = new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }; + fontWeight = new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }; + fontSize = new CssExpression + { + Terms = new List + { + new() { Value = "medium", Type = CssTermType.String }, + }, + }; + lineHeight = new CssExpression + { + Terms = new List + { + new() { Value = "normal", Type = CssTermType.String }, + }, + }; + fontFamily = new CssExpression + { + Terms = new List + { + new() { Value = "serif", Type = CssTermType.String }, + }, + }; var fontFamilyList = new List(); foreach (var term in p.Expression.Terms) { @@ -2442,7 +3206,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep = new Property() { Name = string.Format(shPr.Pattern, direction), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2458,7 +3225,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep = new Property() { Name = string.Format(shPr.Pattern, direction), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2472,7 +3242,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep = new Property() { Name = string.Format(shPr.Pattern, direction), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.Skip(1).First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.Skip(1).First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2486,7 +3259,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep3 = new Property() { Name = string.Format(shPr.Pattern, "top"), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2499,7 +3275,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep2 = new Property() { Name = string.Format(shPr.Pattern, direction), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.Skip(1).First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.Skip(1).First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2511,7 +3290,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep4 = new Property() { Name = string.Format(shPr.Pattern, "bottom"), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.Skip(2).First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.Skip(2).First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2527,7 +3309,10 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo var ep = new Property() { Name = string.Format(shPr.Pattern, direction), - Expression = new CssExpression { Terms = new List { p.Expression.Terms.Skip(skip++).First() } }, + Expression = new CssExpression + { + Terms = new List { p.Expression.Terms.Skip(skip++).First() }, + }, HighOrderSort = p.HighOrderSort, IdAttributesInSelector = p.IdAttributesInSelector, AttributesInSelector = p.AttributesInSelector, @@ -2551,11 +3336,7 @@ private static void ExpandShorthandPropertiesForElement(XElement element, HtmlTo "no-repeat", }; - private static readonly string[] BackgroundAttachmentValues = new[] - { - "scroll", - "fixed", - }; + private static readonly string[] BackgroundAttachmentValues = new[] { "scroll", "fixed" }; private static readonly string[] BackgroundPositionValues = new[] { @@ -2576,18 +3357,23 @@ private static CssDataType GetDatatypeFromBackgroundTerm(CssTerm term) return CssDataType.BackgroundAttachment; if (term.Function != null) return CssDataType.BackgroundImage; - if (term.Unit is CssUnit.CM or CssUnit.EM or CssUnit.IN or CssUnit.MM or CssUnit.PT or CssUnit.PX or CssUnit.Percent) + if ( + term.Unit + is CssUnit.CM + or CssUnit.EM + or CssUnit.IN + or CssUnit.MM + or CssUnit.PT + or CssUnit.PX + or CssUnit.Percent + ) return CssDataType.BackgroundPosition; if (BackgroundPositionValues.Contains(term.Value.ToLower())) return CssDataType.BackgroundPosition; return CssDataType.BackgroundPosition; } - private static readonly string[] ListStylePositionValues = new[] - { - "inside", - "outside", - }; + private static readonly string[] ListStylePositionValues = new[] { "inside", "outside" }; private static readonly string[] BorderStyleValues = new[] { @@ -2641,16 +3427,9 @@ private static CssDataType GetDatatypeFromListStyleTerm(CssTerm term) return CssDataType.ListStyleImage; } - private static readonly string[] FontStyleValues = new[] - { - "italic", - "oblique", - }; + private static readonly string[] FontStyleValues = new[] { "italic", "oblique" }; - private static readonly string[] FontVarientValues = new[] - { - "small-caps", - }; + private static readonly string[] FontVarientValues = new[] { "small-caps" }; private static readonly string[] FontWeightValues = new[] { @@ -2678,7 +3457,16 @@ private static CssDataType GetDatatypeFromFontTerm(CssTerm term) return CssDataType.FontWeight; if (FontSizeMap.ContainsKey(term.Value.ToLower())) return CssDataType.FontSize; - if (term.Unit is CssUnit.CM or CssUnit.EM or CssUnit.IN or CssUnit.MM or CssUnit.PT or CssUnit.PX or CssUnit.Percent) + if ( + term.Unit + is CssUnit.CM + or CssUnit.EM + or CssUnit.IN + or CssUnit.MM + or CssUnit.PT + or CssUnit.PX + or CssUnit.Percent + ) return CssDataType.Length; return CssDataType.FontFamily; } @@ -2889,6 +3677,7 @@ public class Property : IComparable public int AttributesInSelector { get; set; } public int ElementNamesInSelector { get; set; } public int SequenceNumber { get; set; } + public enum HighOrderPriority { InitialValue = 0, @@ -2931,30 +3720,31 @@ int IComparable.CompareTo(Property other) } } - private static readonly Dictionary ColorMap = new() - { - { "maroon", "800000" }, - { "red", "FF0000" }, - { "orange", "FFA500" }, - { "yellow", "FFFF00" }, - { "olive", "808000" }, - { "purple", "800080" }, - { "fuchsia", "FF00FF" }, - { "white", "FFFFFF" }, - { "lime", "00FF00" }, - { "green", "008000" }, - { "navy", "000080" }, - { "blue", "0000FF" }, - { "mediumblue", "0000CD" }, - { "aqua", "00FFFF" }, - { "teal", "008080" }, - { "black", "000000" }, - { "silver", "C0C0C0" }, - { "gray", "808080" }, - { "darkgray", "A9A9A9" }, - { "beige", "F5F5DC" }, - { "windowtext", "000000" }, - }; + private static readonly Dictionary ColorMap = + new() + { + { "maroon", "800000" }, + { "red", "FF0000" }, + { "orange", "FFA500" }, + { "yellow", "FFFF00" }, + { "olive", "808000" }, + { "purple", "800080" }, + { "fuchsia", "FF00FF" }, + { "white", "FFFFFF" }, + { "lime", "00FF00" }, + { "green", "008000" }, + { "navy", "000080" }, + { "blue", "0000FF" }, + { "mediumblue", "0000CD" }, + { "aqua", "00FFFF" }, + { "teal", "008080" }, + { "black", "000000" }, + { "silver", "C0C0C0" }, + { "gray", "808080" }, + { "darkgray", "A9A9A9" }, + { "beige", "F5F5DC" }, + { "windowtext", "000000" }, + }; public static string GetWmlColorFromExpression(CssExpression color) { @@ -2962,7 +3752,11 @@ public static string GetWmlColorFromExpression(CssExpression color) if (color.Terms.Count == 1) { var term = color.Terms.First(); - if (term.Type == CssTermType.Function && term.Function.Name.ToUpper() == "RGB" && term.Function.Expression.Terms.Count == 3) + if ( + term.Type == CssTermType.Function + && term.Function.Name.ToUpper() == "RGB" + && term.Function.Expression.Terms.Count == 3 + ) { var lt = term.Function.Expression.Terms; if (lt.First().Unit == CssUnit.Percent) @@ -2986,9 +3780,10 @@ public static string GetWmlColorFromExpression(CssExpression color) var value = term.Value; if (value.Substring(0, 1) == "#" && value.Length == 4) { - var e = ConvertSingleDigit(value.Substring(1, 1)) + - ConvertSingleDigit(value.Substring(2, 1)) + - ConvertSingleDigit(value.Substring(3, 1)); + var e = + ConvertSingleDigit(value.Substring(1, 1)) + + ConvertSingleDigit(value.Substring(2, 1)) + + ConvertSingleDigit(value.Substring(3, 1)); return e; } if (value.Substring(0, 1) == "#") diff --git a/Clippit/Html/HtmlToWmlCssParser.cs b/Clippit/Html/HtmlToWmlCssParser.cs index 94a1d211..d65a6491 100644 --- a/Clippit/Html/HtmlToWmlCssParser.cs +++ b/Clippit/Html/HtmlToWmlCssParser.cs @@ -40,13 +40,8 @@ public CssAttributeOperator? Operator public string CssOperatorString { - get - { - return this.m_op?.ToString(); - } - set { - this.m_op = (CssAttributeOperator)Enum.Parse(typeof(CssAttributeOperator), value); - } + get { return this.m_op?.ToString(); } + set { this.m_op = (CssAttributeOperator)Enum.Parse(typeof(CssAttributeOperator), value); } } public string Value { get; set; } @@ -349,8 +344,7 @@ private string ToPageString(string start) return sb.ToString(); } - private string ToCharSetString(string start) => - $"{start}{Name} {Expression}"; + private string ToCharSetString(string start) => $"{start}{Name} {Expression}"; } public enum CssDirectiveType @@ -370,18 +364,12 @@ public class CssExpression public bool IsNotAuto { - get - { - return (this != null && this.ToString() != "auto"); - } + get { return (this != null && this.ToString() != "auto"); } } public bool IsAuto { - get - { - return (this.ToString() == "auto"); - } + get { return (this.ToString() == "auto"); } } public bool IsNotNormal @@ -391,10 +379,7 @@ public bool IsNotNormal public bool IsNormal { - get - { - return (this.ToString() == "normal"); - } + get { return (this.ToString() == "normal"); } } public override string ToString() @@ -416,8 +401,7 @@ public override string ToString() return sb.ToString(); } - public static implicit operator string(CssExpression e) => - e.ToString(); + public static implicit operator string(CssExpression e) => e.ToString(); public static explicit operator double(CssExpression e) => double.Parse(e.Terms.First().Value, CultureInfo.InvariantCulture); @@ -520,7 +504,7 @@ public enum CssMedium projection, screen, tty, - tv + tv, } public class CssPropertyValue @@ -548,14 +532,16 @@ public bool IsColor { get { - if (((Type == CssValueType.Hex) - || (Type == CssValueType.String && Value.StartsWith("#"))) - && (Value.Length == 6 || (Value.Length == 7 && Value.StartsWith("#")))) + if ( + ((Type == CssValueType.Hex) || (Type == CssValueType.String && Value.StartsWith("#"))) + && (Value.Length == 6 || (Value.Length == 7 && Value.StartsWith("#"))) + ) { var hex = true; foreach (var c in Value) { - if (!char.IsDigit(c) + if ( + !char.IsDigit(c) && c != '#' && c != 'a' && c != 'A' @@ -587,7 +573,10 @@ public bool IsColor break; } } - if (number) { return false; } + if (number) + { + return false; + } if (ColorParser.IsValidName(Value)) { @@ -607,7 +596,7 @@ public Color ToColor() { 7 when Value.StartsWith("#") => Value.Substring(1), 6 => Value, - _ => hex + _ => hex, }; } else @@ -638,7 +627,7 @@ private int ConvertFromHex(string input) "D" => 13, "E" => 14, "F" => 15, - _ => int.Parse(chunk) + _ => int.Parse(chunk), }; if (i == 0) { @@ -730,16 +719,13 @@ public class CssSimpleSelector public CssCombinator? Combinator { - get { - return m_combinator; - } - set { - m_combinator = value; - } + get { return m_combinator; } + set { m_combinator = value; } } public string CombinatorString { - get { + get + { if (this.m_combinator.HasValue) { return m_combinator.ToString(); @@ -749,9 +735,7 @@ public string CombinatorString return null; } } - set { - this.m_combinator = (CssCombinator)Enum.Parse(typeof(CssCombinator), value); - } + set { this.m_combinator = (CssCombinator)Enum.Parse(typeof(CssCombinator), value); } } public string ElementName { get; set; } @@ -901,7 +885,7 @@ public enum CssTagType Classed = 2, IDed = 4, Pseudoed = 8, - Directive = 16 + Directive = 16, } public class CssTerm @@ -912,40 +896,24 @@ public class CssTerm public char? Separator { - get { - return m_separator; - } - set { - m_separator = value; - } + get { return m_separator; } + set { m_separator = value; } } public string SeparatorChar { - get { - return m_separator.HasValue ? this.m_separator.Value.ToString() : null; - } - set { - m_separator = !string.IsNullOrEmpty(value) ? value[0] : '\0'; - } + get { return m_separator.HasValue ? this.m_separator.Value.ToString() : null; } + set { m_separator = !string.IsNullOrEmpty(value) ? value[0] : '\0'; } } public char? Sign { - get { - return m_sign; - } - set { - m_sign = value; - } + get { return m_sign; } + set { m_sign = value; } } public string SignChar { - get { - return this.m_sign.HasValue ? this.m_sign.Value.ToString() : null; - } - set { - this.m_sign = !string.IsNullOrEmpty(value) ? value[0] : '\0'; - } + get { return this.m_sign.HasValue ? this.m_sign.Value.ToString() : null; } + set { this.m_sign = !string.IsNullOrEmpty(value) ? value[0] : '\0'; } } public CssTermType Type { get; set; } @@ -954,16 +922,13 @@ public string SignChar public CssUnit? Unit { - get { - return m_unit; - } - set { - m_unit = value; - } + get { return m_unit; } + set { m_unit = value; } } public string UnitString { - get { + get + { if (this.m_unit.HasValue) { return this.m_unit.ToString(); @@ -973,9 +938,7 @@ public string UnitString return null; } } - set { - this.m_unit = (CssUnit)Enum.Parse(typeof(CssUnit), value); - } + set { this.m_unit = (CssUnit)Enum.Parse(typeof(CssUnit), value); } } public CssFunction Function { get; set; } @@ -1027,15 +990,16 @@ public bool IsColor { get { - if (((Type == CssTermType.Hex) - || (Type == CssTermType.String && Value.StartsWith("#"))) - && (Value.Length is 6 or 3 || (Value.Length is 7 or 4 - && Value.StartsWith("#")))) + if ( + ((Type == CssTermType.Hex) || (Type == CssTermType.String && Value.StartsWith("#"))) + && (Value.Length is 6 or 3 || (Value.Length is 7 or 4 && Value.StartsWith("#"))) + ) { var hex = true; foreach (var c in Value) { - if (!char.IsDigit(c) + if ( + !char.IsDigit(c) && c != '#' && c != 'a' && c != 'A' @@ -1067,7 +1031,8 @@ public bool IsColor break; } } - if (number) { + if (number) + { return false; } @@ -1078,9 +1043,10 @@ public bool IsColor } else if (Type == CssTermType.Function) { - if ((Function.Name.ToLower().Equals("rgb") && Function.Expression.Terms.Count == 3) + if ( + (Function.Name.ToLower().Equals("rgb") && Function.Expression.Terms.Count == 3) || (Function.Name.ToLower().Equals("rgba") && Function.Expression.Terms.Count == 4) - ) + ) { for (var i = 0; i < Function.Expression.Terms.Count; i++) { @@ -1091,9 +1057,10 @@ public bool IsColor } return true; } - else if ((Function.Name.ToLower().Equals("hsl") && Function.Expression.Terms.Count == 3) - || (Function.Name.ToLower().Equals("hsla") && Function.Expression.Terms.Count == 4) - ) + else if ( + (Function.Name.ToLower().Equals("hsl") && Function.Expression.Terms.Count == 3) + || (Function.Name.ToLower().Equals("hsla") && Function.Expression.Terms.Count == 4) + ) { for (var i = 0; i < Function.Expression.Terms.Count; i++) { @@ -1142,16 +1109,19 @@ public Color ToColor() { 7 or 4 when Value.StartsWith("#") => Value.Substring(1), 6 or 3 => Value, - _ => hex + _ => hex, }; } else if (Type == CssTermType.Function) { - if ((Function.Name.ToLower().Equals("rgb") && Function.Expression.Terms.Count == 3) + if ( + (Function.Name.ToLower().Equals("rgb") && Function.Expression.Terms.Count == 3) || (Function.Name.ToLower().Equals("rgba") && Function.Expression.Terms.Count == 4) - ) + ) { - int fr = 0, fg = 0, fb = 0; + int fr = 0, + fg = 0, + fb = 0; for (var i = 0; i < Function.Expression.Terms.Count; i++) { if (Function.Expression.Terms[i].Type != CssTermType.Number) @@ -1160,31 +1130,43 @@ 7 or 4 when Value.StartsWith("#") => Value.Substring(1), } switch (i) { - case 0: fr = GetRGBValue(Function.Expression.Terms[i]); + case 0: + fr = GetRGBValue(Function.Expression.Terms[i]); break; - case 1: fg = GetRGBValue(Function.Expression.Terms[i]); + case 1: + fg = GetRGBValue(Function.Expression.Terms[i]); break; - case 2: fb = GetRGBValue(Function.Expression.Terms[i]); + case 2: + fb = GetRGBValue(Function.Expression.Terms[i]); break; } } return Color.FromArgb(fr, fg, fb); } - else if ((Function.Name.ToLower().Equals("hsl") && Function.Expression.Terms.Count == 3) - || (Function.Name.Equals("hsla") && Function.Expression.Terms.Count == 4) - ) + else if ( + (Function.Name.ToLower().Equals("hsl") && Function.Expression.Terms.Count == 3) + || (Function.Name.Equals("hsla") && Function.Expression.Terms.Count == 4) + ) { - int h = 0, s = 0, v = 0; + int h = 0, + s = 0, + v = 0; for (var i = 0; i < Function.Expression.Terms.Count; i++) { - if (Function.Expression.Terms[i].Type != CssTermType.Number) { return Color.Black; } + if (Function.Expression.Terms[i].Type != CssTermType.Number) + { + return Color.Black; + } switch (i) { - case 0: h = GetHueValue(Function.Expression.Terms[i]); + case 0: + h = GetHueValue(Function.Expression.Terms[i]); break; - case 1: s = GetRGBValue(Function.Expression.Terms[i]); + case 1: + s = GetRGBValue(Function.Expression.Terms[i]); break; - case 2: v = GetRGBValue(Function.Expression.Terms[i]); + case 2: + v = GetRGBValue(Function.Expression.Terms[i]); break; } } @@ -1213,6 +1195,7 @@ 7 or 4 when Value.StartsWith("#") => Value.Substring(1), var b = ConvertFromHex(hex.Substring(4)); return Color.FromArgb(r, g, b); } + private int ConvertFromHex(string input) { int val; @@ -1228,7 +1211,7 @@ private int ConvertFromHex(string input) "D" => 13, "E" => 14, "F" => 15, - _ => int.Parse(chunk) + _ => int.Parse(chunk), }; if (i == 0) { @@ -1250,7 +1233,7 @@ public enum CssTermType String, Url, Unicode, - Hex + Hex, } public enum CssUnit @@ -1290,7 +1273,7 @@ public static string ToString(CssUnit u) CssUnit.Percent => "%", CssUnit.Hz or CssUnit.kHz => u.ToString(), CssUnit.None => "", - _ => u.ToString().ToLower() + _ => u.ToString().ToLower(), }; } } @@ -1302,7 +1285,7 @@ public enum CssValueType Unit, Percent, Url, - Function + Function, } public class CssParser @@ -1347,6 +1330,7 @@ public HueSatVal(int h, int s, int v) Saturation = s; Value = v; } + public HueSatVal(Color color) { Hue = 0; @@ -1354,6 +1338,7 @@ public HueSatVal(Color color) Value = 0; ConvertFromRGB(color); } + public int Hue { get; set; } public int Saturation { get; set; } @@ -1362,19 +1347,17 @@ public HueSatVal(Color color) public Color Color { - get { - return ConvertToRGB(); - } - set { - ConvertFromRGB(value); - } + get { return ConvertToRGB(); } + set { ConvertFromRGB(value); } } + private void ConvertFromRGB(Color color) { var r = color.R / 255.0d; var g = color.G / 255.0d; var b = color.B / 255.0d; - double h; double s; + double h; + double s; var min = Math.Min(Math.Min(r, g), b); var max = Math.Max(Math.Max(r, g), b); @@ -1530,7 +1513,28 @@ private bool IsInHex(string value) } var hexes = new List { - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "a", "b", "c", "d", "e", "f" + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", + "a", + "b", + "c", + "d", + "e", + "f", }; foreach (var c in m_lookaheadToken.m_tokenValue) { @@ -1551,8 +1555,30 @@ private bool IsUnitOfLength() var units = new List( new string[] { - "em", "ex", "px", "gd", "rem", "vw", "vh", "vm", "ch", "mm", "cm", "in", "pt", "pc", "deg", "grad", "rad", "turn", "ms", "s", "hz", "khz" - }); + "em", + "ex", + "px", + "gd", + "rem", + "vw", + "vh", + "vm", + "ch", + "mm", + "cm", + "in", + "pt", + "pc", + "deg", + "grad", + "rad", + "turn", + "ms", + "s", + "hz", + "khz", + } + ); return units.Contains(m_lookaheadToken.m_tokenValue.ToLower()); } @@ -1587,7 +1613,7 @@ public void SemanticErr(string msg) private void Get() { - for (;;) + for (; ; ) { m_lastRecognizedToken = m_lookaheadToken; m_lookaheadToken = m_scanner.Scan(); @@ -1628,7 +1654,6 @@ private void ExpectWeak(int n, int follow) } } - private bool WeakSeparator(int n, int syFol, int repFol) { var kind = m_lookaheadToken.m_tokenKind; @@ -1653,7 +1678,6 @@ private bool WeakSeparator(int n, int syFol, int repFol) } } - private void Css3() { CssDoc = new CssDocument(); @@ -1806,7 +1830,7 @@ private void Directive(out CssDirective dir) "@page" => CssDirectiveType.Page, "@font-face" => CssDirectiveType.FontFace, "@namespace" => CssDirectiveType.Namespace, - _ => CssDirectiveType.Other + _ => CssDirectiveType.Other, }; while (m_lookaheadToken.m_tokenKind == 4) @@ -1929,7 +1953,8 @@ private void Directive(out CssDirective dir) Get(); } } - else SyntaxErr(50); + else + SyntaxErr(50); } private void QuotedString(out string qs) @@ -1963,8 +1988,8 @@ private void QuotedString(out string qs) } Expect(8); } - else SyntaxErr(51); - + else + SyntaxErr(51); } private void URI(out string url) @@ -1999,7 +2024,8 @@ private void URI(out string url) } } } - else SyntaxErr(52); + else + SyntaxErr(52); while (m_lookaheadToken.m_tokenKind == 4) { Get(); @@ -2016,66 +2042,68 @@ private void Medium(out CssMedium m) switch (m_lookaheadToken.m_tokenKind) { case 12: - { - Get(); - m = CssMedium.all; - break; - } + { + Get(); + m = CssMedium.all; + break; + } case 13: - { - Get(); - m = CssMedium.aural; - break; - } + { + Get(); + m = CssMedium.aural; + break; + } case 14: - { - Get(); - m = CssMedium.braille; - break; - } + { + Get(); + m = CssMedium.braille; + break; + } case 15: - { - Get(); - m = CssMedium.embossed; - break; - } + { + Get(); + m = CssMedium.embossed; + break; + } case 16: - { - Get(); - m = CssMedium.handheld; - break; - } + { + Get(); + m = CssMedium.handheld; + break; + } case 17: - { - Get(); - m = CssMedium.print; - break; - } + { + Get(); + m = CssMedium.print; + break; + } case 18: - { - Get(); - m = CssMedium.projection; - break; - } + { + Get(); + m = CssMedium.projection; + break; + } case 19: - { - Get(); - m = CssMedium.screen; - break; - } + { + Get(); + m = CssMedium.screen; + break; + } case 20: - { - Get(); - m = CssMedium.tty; - break; - } + { + Get(); + m = CssMedium.tty; + break; + } case 21: - { - Get(); - m = CssMedium.tv; - break; - } - default: SyntaxErr(53); break; + { + Get(); + m = CssMedium.tv; + break; + } + default: + SyntaxErr(53); + break; } } @@ -2085,71 +2113,73 @@ private void Identity(out string ident) switch (m_lookaheadToken.m_tokenKind) { case 1: - { - Get(); - break; - } + { + Get(); + break; + } case 22: - { - Get(); - break; - } + { + Get(); + break; + } case 9: - { - Get(); - break; - } + { + Get(); + break; + } case 12: - { - Get(); - break; - } + { + Get(); + break; + } case 13: - { - Get(); - break; - } + { + Get(); + break; + } case 14: - { - Get(); - break; - } + { + Get(); + break; + } case 15: - { - Get(); - break; - } + { + Get(); + break; + } case 16: - { - Get(); - break; - } + { + Get(); + break; + } case 17: - { - Get(); - break; - } + { + Get(); + break; + } case 18: - { - Get(); - break; - } + { + Get(); + break; + } case 19: - { - Get(); - break; - } + { + Get(); + break; + } case 20: - { - Get(); - break; - } + { + Get(); + break; + } case 21: - { - Get(); - break; - } - default: SyntaxErr(54); break; + { + Get(); + break; + } + default: + SyntaxErr(54); + break; } ident += m_lastRecognizedToken.m_tokenValue; } @@ -2362,7 +2392,8 @@ private void SimpleSelector(out CssSimpleSelector ss) ss.Pseudo = psd; } } - else SyntaxErr(55); + else + SyntaxErr(55); while (StartOf(13)) { var child = new CssSimpleSelector(); @@ -2408,7 +2439,6 @@ private void SimpleSelector(out CssSimpleSelector ss) } parent.Child = child; parent = child; - } } @@ -2435,41 +2465,41 @@ private void Attrib(out CssAttribute atb) switch (m_lookaheadToken.m_tokenKind) { case 36: - { - Get(); - atb.Operator = CssAttributeOperator.Equals; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.Equals; + break; + } case 37: - { - Get(); - atb.Operator = CssAttributeOperator.InList; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.InList; + break; + } case 38: - { - Get(); - atb.Operator = CssAttributeOperator.Hyphenated; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.Hyphenated; + break; + } case 39: - { - Get(); - atb.Operator = CssAttributeOperator.EndsWith; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.EndsWith; + break; + } case 40: - { - Get(); - atb.Operator = CssAttributeOperator.BeginsWith; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.BeginsWith; + break; + } case 41: - { - Get(); - atb.Operator = CssAttributeOperator.Contains; - break; - } + { + Get(); + atb.Operator = CssAttributeOperator.Contains; + break; + } } while (m_lookaheadToken.m_tokenKind == 4) { @@ -2490,7 +2520,8 @@ private void Attrib(out CssAttribute atb) QuotedString(out quote); atb.Value = quote; } - else SyntaxErr(56); + else + SyntaxErr(56); while (m_lookaheadToken.m_tokenKind == 4) { Get(); @@ -2550,7 +2581,8 @@ private void Term(out CssTerm trm) if (m_lookaheadToken.m_tokenKind is 7 or 8) { QuotedString(out val); - trm.Value = val; trm.Type = CssTermType.String; + trm.Value = val; + trm.Type = CssTermType.String; } else if (m_lookaheadToken.m_tokenKind == 9) { @@ -2634,7 +2666,8 @@ private void Term(out CssTerm trm) } } } - else SyntaxErr(57); + else + SyntaxErr(57); } else if (m_lookaheadToken.m_tokenKind == 34) { @@ -2670,7 +2703,8 @@ private void Term(out CssTerm trm) trm.Value += m_lastRecognizedToken.m_tokenValue; } } - else SyntaxErr(58); + else + SyntaxErr(58); } } } @@ -2703,7 +2737,10 @@ private void Term(out CssTerm trm) Get(); trm.Sign = '+'; } - if (minus) { trm.Sign = '-'; } + if (minus) + { + trm.Sign = '-'; + } while (m_lookaheadToken.m_tokenKind == 3) { Get(); @@ -2762,18 +2799,23 @@ private void Term(out CssTerm trm) } catch { - m_errors.SemanticError(m_lastRecognizedToken.m_tokenLine, m_lastRecognizedToken.m_tokenColumn, - $"Unrecognized unit '{ident}'"); + m_errors.SemanticError( + m_lastRecognizedToken.m_tokenLine, + m_lastRecognizedToken.m_tokenColumn, + $"Unrecognized unit '{ident}'" + ); } - } } } - trm.Value = val; trm.Type = CssTermType.Number; + trm.Value = val; + trm.Type = CssTermType.Number; } - else SyntaxErr(59); + else + SyntaxErr(59); } - else SyntaxErr(60); + else + SyntaxErr(60); } private void HexValue(out string val) @@ -2794,9 +2836,11 @@ private void HexValue(out string val) else if (IsInHex(val)) { Expect(1); - val += m_lastRecognizedToken.m_tokenValue; found = true; + val += m_lastRecognizedToken.m_tokenValue; + found = true; } - else SyntaxErr(61); + else + SyntaxErr(61); if (!found && IsInHex(val)) { Expect(1); @@ -2813,32 +2857,1124 @@ public void Parse() Expect(0); } - private static readonly bool[,] set = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,x,T, T,x,x,T, T,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,T,T,T, x,T,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,T, T,x,x,x, T,x,x,x, T,T,T,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,T,T,T, T,T,T,x, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, - {x,T,T,T, T,T,T,T, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, - {x,T,T,T, T,T,T,T, T,T,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x}, - {x,T,x,T, T,x,x,T, T,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,T,x,x, x,T,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x}, - {x,T,x,x, T,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,x,x,x, x,T,T,T, T,T,T,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x}, - {x,T,x,T, T,x,x,T, T,T,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x,x, T,T,T,T, x,x,x,x, x,x,x,T, T,x,T,T, T,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x}, - {x,T,x,T, T,x,x,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,x,x, T,T,T,T, T,x,x,x, x,x,x,T, T,x,T,T, T,x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x} - }; + private static readonly bool[,] set = + { + { + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + T, + T, + x, + x, + T, + T, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + T, + T, + T, + x, + T, + x, + x, + x, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + x, + x, + }, + { + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + T, + x, + x, + x, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + T, + T, + T, + T, + T, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + }, + { + x, + T, + T, + T, + T, + T, + T, + T, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + }, + { + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + }, + { + x, + T, + T, + T, + x, + T, + T, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + }, + { + x, + T, + x, + T, + T, + x, + x, + T, + T, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + T, + x, + x, + x, + T, + x, + x, + x, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + x, + x, + }, + { + x, + T, + x, + x, + T, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + x, + x, + x, + x, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + T, + T, + x, + x, + T, + T, + T, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + T, + T, + x, + T, + T, + T, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + x, + T, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + x, + x, + x, + x, + x, + }, + { + x, + T, + x, + T, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + T, + T, + x, + T, + T, + T, + x, + x, + }, + { + x, + T, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + T, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + x, + T, + x, + x, + }, + }; } - public class Errors { public int numberOfErrorsDetected = 0; @@ -2910,7 +4046,7 @@ public virtual void SyntaxError(int line, int col, int n) 59 => "invalid term", 60 => "invalid term", 61 => "invalid HexValue", - _ => "error " + n + _ => "error " + n, }; var errorString = string.Format(errMsgFormat, line, col, s); throw new OpenXmlPowerToolsException(errorString); @@ -2939,10 +4075,10 @@ public virtual void Warning(string s) } } - public class FatalError : Exception { - public FatalError(string m) : base(m) { } + public FatalError(string m) + : base(m) { } } public class CssToken @@ -2971,7 +4107,8 @@ public class CssBuffer public CssBuffer(Stream s, bool isUserStream) { - m_inputStream = s; this.m_isUserStream = isUserStream; + m_inputStream = s; + this.m_isUserStream = isUserStream; if (m_inputStream.CanSeek) { @@ -3006,7 +4143,10 @@ protected CssBuffer(CssBuffer b) m_isUserStream = b.m_isUserStream; } - ~CssBuffer() { Close(); } + ~CssBuffer() + { + Close(); + } private void Close() { @@ -3064,7 +4204,8 @@ public int Pos { if (value >= m_inputStreamLength && m_inputStream != null && !m_inputStream.CanSeek) { - while (value >= m_inputStreamLength && ReadNextStreamChunk() > 0) ; + while (value >= m_inputStreamLength && ReadNextStreamChunk() > 0) + ; } if (value < 0 || value > m_inputStreamLength) @@ -3080,7 +4221,8 @@ public int Pos { m_inputStream.Seek(value, SeekOrigin.Begin); m_bufferLength = m_inputStream.Read(m_inputBuffer, 0, m_inputBuffer.Length); - m_bufferStart = value; m_currentPositionInBuffer = 0; + m_bufferStart = value; + m_currentPositionInBuffer = 0; } else { @@ -3111,7 +4253,8 @@ private int ReadNextStreamChunk() public class UTF8Buffer : CssBuffer { - public UTF8Buffer(CssBuffer b) : base(b) { } + public UTF8Buffer(CssBuffer b) + : base(b) { } public override int Read() { @@ -3232,7 +4375,6 @@ static Scanner() s_start[85] = 43; s_start[37] = 39; s_start[CssBuffer.EOF] = -1; - } public Scanner(string fileName) @@ -3271,7 +4413,7 @@ private void Init() var ch2 = m_currentInputCharacter; if (ch1 != 0xBB || ch2 != 0xBF) { - throw new FatalError($"illegal byte order mark: EF {ch1,2:X} {ch2,2:X}"); + throw new FatalError($"illegal byte order mark: EF {ch1, 2:X} {ch2, 2:X}"); } m_scannerBuffer = new UTF8Buffer(m_scannerBuffer); m_columnNumberOfCurrentCharacter = 0; @@ -3298,10 +4440,10 @@ private void NextCh() m_currentInputCharacter = END_OF_LINE; if (m_currentInputCharacter == END_OF_LINE) { - m_lineNumberOfCurrentCharacter++; m_columnNumberOfCurrentCharacter = 0; + m_lineNumberOfCurrentCharacter++; + m_columnNumberOfCurrentCharacter = 0; } } - } private void AddCh() @@ -3321,12 +4463,16 @@ private void AddCh() private bool Comment0() { - int level = 1, pos0 = m_currentCharacterBytePosition, line0 = m_lineNumberOfCurrentCharacter, col0 = m_columnNumberOfCurrentCharacter, charPos0 = m_unicodeCharacterPosition; + int level = 1, + pos0 = m_currentCharacterBytePosition, + line0 = m_lineNumberOfCurrentCharacter, + col0 = m_columnNumberOfCurrentCharacter, + charPos0 = m_unicodeCharacterPosition; NextCh(); if (m_currentInputCharacter == '*') { NextCh(); - for (;;) + for (; ; ) { if (m_currentInputCharacter == '*') { @@ -3360,7 +4506,6 @@ private bool Comment0() return false; } - private void CheckLiteral() { switch (m_currentToken.m_tokenValue) @@ -3427,7 +4572,8 @@ private CssToken NextToken() { state = (int)s_start[m_currentInputCharacter]; } - else { + else + { state = 0; } m_lengthOfCurrentToken = 0; @@ -3435,48 +4581,57 @@ private CssToken NextToken() switch (state) { - case -1: { + case -1: + { m_currentToken.m_tokenKind = c_eof; break; } case 0: + { + if (recKind != c_noSym) { - if (recKind != c_noSym) - { - m_lengthOfCurrentToken = recEnd - m_currentToken.m_tokenPositionInBytes; - SetScannerBehindT(); - } - m_currentToken.m_tokenKind = recKind; - break; + m_lengthOfCurrentToken = recEnd - m_currentToken.m_tokenPositionInBytes; + SetScannerBehindT(); } + m_currentToken.m_tokenKind = recKind; + break; + } case 1: - recEnd = m_currentCharacterBytePosition; recKind = 1; - if (m_currentInputCharacter == '-' || m_currentInputCharacter >= '0' && m_currentInputCharacter <= '9' || m_currentInputCharacter >= 'A' && m_currentInputCharacter <= 'Z' || m_currentInputCharacter == '_' || m_currentInputCharacter >= 'a' && m_currentInputCharacter <= 'z') + recEnd = m_currentCharacterBytePosition; + recKind = 1; + if ( + m_currentInputCharacter == '-' + || m_currentInputCharacter >= '0' && m_currentInputCharacter <= '9' + || m_currentInputCharacter >= 'A' && m_currentInputCharacter <= 'Z' + || m_currentInputCharacter == '_' + || m_currentInputCharacter >= 'a' && m_currentInputCharacter <= 'z' + ) { AddCh(); goto case 1; } else { - m_currentToken.m_tokenKind = 1; m_currentToken.m_tokenValue = new string(m_textOfCurrentToken, 0, m_lengthOfCurrentToken); + m_currentToken.m_tokenKind = 1; + m_currentToken.m_tokenValue = new string(m_textOfCurrentToken, 0, m_lengthOfCurrentToken); CheckLiteral(); return m_currentToken; } case 2: - { - m_currentToken.m_tokenKind = 2; - break; - } + { + m_currentToken.m_tokenKind = 2; + break; + } case 3: - { - m_currentToken.m_tokenKind = 3; - break; - } + { + m_currentToken.m_tokenKind = 3; + break; + } case 4: - { - m_currentToken.m_tokenKind = 4; - break; - } + { + m_currentToken.m_tokenKind = 4; + break; + } case 5: if (m_currentInputCharacter == '!') { @@ -3493,7 +4648,8 @@ private CssToken NextToken() AddCh(); goto case 7; } - else { + else + { goto case 0; } case 7: @@ -3507,10 +4663,10 @@ private CssToken NextToken() goto case 0; } case 8: - { - m_currentToken.m_tokenKind = 5; - break; - } + { + m_currentToken.m_tokenKind = 5; + break; + } case 9: if (m_currentInputCharacter == '>') { @@ -3522,118 +4678,120 @@ private CssToken NextToken() goto case 0; } case 10: - { - m_currentToken.m_tokenKind = 6; - break; - } + { + m_currentToken.m_tokenKind = 6; + break; + } case 11: - { - m_currentToken.m_tokenKind = 7; - break; - } + { + m_currentToken.m_tokenKind = 7; + break; + } case 12: - { - m_currentToken.m_tokenKind = 8; - break; - } + { + m_currentToken.m_tokenKind = 8; + break; + } case 13: - { - m_currentToken.m_tokenKind = 10; - break; - } + { + m_currentToken.m_tokenKind = 10; + break; + } case 14: - { - m_currentToken.m_tokenKind = 11; - break; - } + { + m_currentToken.m_tokenKind = 11; + break; + } case 15: - { - m_currentToken.m_tokenKind = 23; - break; - } + { + m_currentToken.m_tokenKind = 23; + break; + } case 16: - { - m_currentToken.m_tokenKind = 25; - break; - } + { + m_currentToken.m_tokenKind = 25; + break; + } case 17: - { - m_currentToken.m_tokenKind = 26; - break; - } + { + m_currentToken.m_tokenKind = 26; + break; + } case 18: - { - m_currentToken.m_tokenKind = 27; - break; - } + { + m_currentToken.m_tokenKind = 27; + break; + } case 19: - { - m_currentToken.m_tokenKind = 28; - break; - } + { + m_currentToken.m_tokenKind = 28; + break; + } case 20: - { - m_currentToken.m_tokenKind = 29; - break; - } + { + m_currentToken.m_tokenKind = 29; + break; + } case 21: - { - m_currentToken.m_tokenKind = 30; - break; - } + { + m_currentToken.m_tokenKind = 30; + break; + } case 22: - { - m_currentToken.m_tokenKind = 33; - break; - } + { + m_currentToken.m_tokenKind = 33; + break; + } case 23: - { - m_currentToken.m_tokenKind = 34; - break; - } + { + m_currentToken.m_tokenKind = 34; + break; + } case 24: - { - m_currentToken.m_tokenKind = 35; - break; - } + { + m_currentToken.m_tokenKind = 35; + break; + } case 25: - { - m_currentToken.m_tokenKind = 36; - break; - } + { + m_currentToken.m_tokenKind = 36; + break; + } case 26: - { - m_currentToken.m_tokenKind = 37; - break; - } + { + m_currentToken.m_tokenKind = 37; + break; + } case 27: if (m_currentInputCharacter == '=') { AddCh(); goto case 28; } - else { + else + { goto case 0; } case 28: - { - m_currentToken.m_tokenKind = 38; - break; - } + { + m_currentToken.m_tokenKind = 38; + break; + } case 29: if (m_currentInputCharacter == '=') { AddCh(); goto case 30; } - else { + else + { goto case 0; } case 30: - { - m_currentToken.m_tokenKind = 39; - break; - } + { + m_currentToken.m_tokenKind = 39; + break; + } case 31: if (m_currentInputCharacter == '=') { @@ -3645,45 +4803,45 @@ private CssToken NextToken() goto case 0; } case 32: - { - m_currentToken.m_tokenKind = 40; - break; - } + { + m_currentToken.m_tokenKind = 40; + break; + } case 33: - { - m_currentToken.m_tokenKind = 41; - break; - } + { + m_currentToken.m_tokenKind = 41; + break; + } case 34: - { - m_currentToken.m_tokenKind = 42; - break; - } + { + m_currentToken.m_tokenKind = 42; + break; + } case 35: - { - m_currentToken.m_tokenKind = 43; - break; - } + { + m_currentToken.m_tokenKind = 43; + break; + } case 36: - { - m_currentToken.m_tokenKind = 44; - break; - } + { + m_currentToken.m_tokenKind = 44; + break; + } case 37: - { - m_currentToken.m_tokenKind = 46; - break; - } + { + m_currentToken.m_tokenKind = 46; + break; + } case 38: - { - m_currentToken.m_tokenKind = 47; - break; - } + { + m_currentToken.m_tokenKind = 47; + break; + } case 39: - { - m_currentToken.m_tokenKind = 48; - break; - } + { + m_currentToken.m_tokenKind = 48; + break; + } case 40: recEnd = m_currentCharacterBytePosition; recKind = 24; @@ -3724,8 +4882,15 @@ private CssToken NextToken() break; } case 43: - recEnd = m_currentCharacterBytePosition; recKind = 1; - if (m_currentInputCharacter == '-' || m_currentInputCharacter >= '0' && m_currentInputCharacter <= '9' || m_currentInputCharacter >= 'A' && m_currentInputCharacter <= 'Z' || m_currentInputCharacter == '_' || m_currentInputCharacter >= 'a' && m_currentInputCharacter <= 'z') + recEnd = m_currentCharacterBytePosition; + recKind = 1; + if ( + m_currentInputCharacter == '-' + || m_currentInputCharacter >= '0' && m_currentInputCharacter <= '9' + || m_currentInputCharacter >= 'A' && m_currentInputCharacter <= 'Z' + || m_currentInputCharacter == '_' + || m_currentInputCharacter >= 'a' && m_currentInputCharacter <= 'z' + ) { AddCh(); goto case 1; @@ -3742,7 +4907,6 @@ private CssToken NextToken() CheckLiteral(); return m_currentToken; } - } m_currentToken.m_tokenValue = new string(m_textOfCurrentToken, 0, m_lengthOfCurrentToken); return m_currentToken; @@ -3752,8 +4916,11 @@ private void SetScannerBehindT() { m_scannerBuffer.Pos = m_currentToken.m_tokenPositionInBytes; NextCh(); - m_lineNumberOfCurrentCharacter = m_currentToken.m_tokenLine; m_columnNumberOfCurrentCharacter = m_currentToken.m_tokenColumn; m_unicodeCharacterPosition = m_currentToken.m_tokenPositionInCharacters; - for (var i = 0; i < m_lengthOfCurrentToken; i++) NextCh(); + m_lineNumberOfCurrentCharacter = m_currentToken.m_tokenLine; + m_columnNumberOfCurrentCharacter = m_currentToken.m_tokenColumn; + m_unicodeCharacterPosition = m_currentToken.m_tokenPositionInCharacters; + for (var i = 0; i < m_lengthOfCurrentToken; i++) + NextCh(); } public CssToken Scan() @@ -3788,5 +4955,4 @@ public void ResetPeek() m_currentPeekToken = m_tokensAlreadyPeeked; } } - } diff --git a/Clippit/Internal/ColorParser.cs b/Clippit/Internal/ColorParser.cs index 09bf3a45..61aff548 100644 --- a/Clippit/Internal/ColorParser.cs +++ b/Clippit/Internal/ColorParser.cs @@ -7,8 +7,7 @@ namespace Clippit.Internal; internal static class ColorParser { - public static Color FromName(string name) => - Color.FromName(name); + public static Color FromName(string name) => Color.FromName(name); public static bool TryFromName(string name, out Color color) { @@ -24,6 +23,5 @@ public static bool TryFromName(string name, out Color color) } } - public static bool IsValidName(string name) => - TryFromName(name, out _); + public static bool IsValidName(string name) => TryFromName(name, out _); } diff --git a/Clippit/Internal/TextReplacer.cs b/Clippit/Internal/TextReplacer.cs index 1ef881ab..18a6c40c 100644 --- a/Clippit/Internal/TextReplacer.cs +++ b/Clippit/Internal/TextReplacer.cs @@ -15,6 +15,7 @@ public class TextReplacer private class MatchSemaphore { public int MatchId { get; } + public MatchSemaphore(int matchId) { MatchId = matchId; @@ -25,33 +26,35 @@ private static XObject CloneWithAnnotation(XNode node) { if (node is XElement element) { - var newElement = new XElement(element.Name, + var newElement = new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(CloneWithAnnotation)); + element.Nodes().Select(CloneWithAnnotation) + ); if (element.Annotation() != null) newElement.AddAnnotation(element.Annotation()); } return node; } - private static object WmlSearchAndReplaceTransform(XNode node, - string search, string replace, bool matchCase) + private static object WmlSearchAndReplaceTransform(XNode node, string search, string replace, bool matchCase) { if (node is XElement element) { if (element.Name == W.p) { var contents = element.Descendants(W.t).Select(t => (string)t).StringConcatenate(); - if (contents.Contains(search) || - (!matchCase && contents.ToUpper().Contains(search.ToUpper()))) + if (contents.Contains(search) || (!matchCase && contents.ToUpper().Contains(search.ToUpper()))) { - var paragraphWithSplitRuns = new XElement(W.p, + var paragraphWithSplitRuns = new XElement( + W.p, element.Attributes(), - element.Nodes().Select(n => WmlSearchAndReplaceTransform(n, search, - replace, matchCase))); + element.Nodes().Select(n => WmlSearchAndReplaceTransform(n, search, replace, matchCase)) + ); var subRunArray = paragraphWithSplitRuns .Elements(W.r) - .Where(e => { + .Where(e => + { var subRunElement = e.Elements().FirstOrDefault(el => el.Name != W.rPr); if (subRunElement == null) return false; @@ -60,24 +63,28 @@ private static object WmlSearchAndReplaceTransform(XNode node, .ToArray(); var paragraphChildrenCount = subRunArray.Length; var matchId = 1; - foreach (var pc in subRunArray - .Take(paragraphChildrenCount - (search.Length - 1)) - .Select((c, i) => new { Child = c, Index = i, })) + foreach ( + var pc in subRunArray + .Take(paragraphChildrenCount - (search.Length - 1)) + .Select((c, i) => new { Child = c, Index = i }) + ) { var subSequence = subRunArray.SequenceAt(pc.Index).Take(search.Length); - var zipped = subSequence.PtZip(search, (pcp, c) => new + var zipped = subSequence.PtZip( + search, + (pcp, c) => new { ParagraphChildProjection = pcp, CharacterToCompare = c } + ); + var dontMatch = zipped.Any(z => { - ParagraphChildProjection = pcp, - CharacterToCompare = c, - }); - var dontMatch = zipped.Any(z => { if (z.ParagraphChildProjection.Annotation() != null) return true; bool b; if (matchCase) b = z.ParagraphChildProjection.Value != z.CharacterToCompare.ToString(); else - b = z.ParagraphChildProjection.Value.ToUpper() != z.CharacterToCompare.ToString().ToUpper(); + b = + z.ParagraphChildProjection.Value.ToUpper() + != z.CharacterToCompare.ToString().ToUpper(); return b; }); var match = !dontMatch; @@ -95,94 +102,104 @@ private static object WmlSearchAndReplaceTransform(XNode node, { var elementsToReplace = paragraphWithReplacedRuns .Elements() - .Where(e => { + .Where(e => + { var sem = e.Annotation(); if (sem == null) return false; return sem.MatchId == id; }) .ToList(); - elementsToReplace.First().AddBeforeSelf( - new XElement(W.r, - elementsToReplace.First().Elements(W.rPr), - new XElement(W.t, replace))); + elementsToReplace + .First() + .AddBeforeSelf( + new XElement( + W.r, + elementsToReplace.First().Elements(W.rPr), + new XElement(W.t, replace) + ) + ); elementsToReplace.Remove(); } - var groupedAdjacentRunsWithIdenticalFormatting = - paragraphWithReplacedRuns + var groupedAdjacentRunsWithIdenticalFormatting = paragraphWithReplacedRuns .Elements() .GroupAdjacent(ce => { if (ce.Name != W.r) return "DontConsolidate"; - if (ce.Elements().Where(e => e.Name != W.rPr).Count() != 1 || - ce.Element(W.t) == null) + if (ce.Elements().Where(e => e.Name != W.rPr).Count() != 1 || ce.Element(W.t) == null) return "DontConsolidate"; if (ce.Element(W.rPr) == null) return ""; return ce.Element(W.rPr).ToString(SaveOptions.None); }); - var paragraphWithConsolidatedRuns = new XElement(W.p, + var paragraphWithConsolidatedRuns = new XElement( + W.p, groupedAdjacentRunsWithIdenticalFormatting.Select(g => - { - if (g.Key == "DontConsolidate") - return (object)g; - var textValue = g.Select(r => r.Element(W.t).Value).StringConcatenate(); - XAttribute xs = null; - if (textValue[0] == ' ' || textValue[textValue.Length - 1] == ' ') - xs = new XAttribute(XNamespace.Xml + "space", "preserve"); - return new XElement(W.r, - g.First().Elements(W.rPr), - new XElement(W.t, xs, textValue)); - })); + { + if (g.Key == "DontConsolidate") + return (object)g; + var textValue = g.Select(r => r.Element(W.t).Value).StringConcatenate(); + XAttribute xs = null; + if (textValue[0] == ' ' || textValue[textValue.Length - 1] == ' ') + xs = new XAttribute(XNamespace.Xml + "space", "preserve"); + return new XElement(W.r, g.First().Elements(W.rPr), new XElement(W.t, xs, textValue)); + }) + ); return paragraphWithConsolidatedRuns; } return element; } if (element.Name == W.r && element.Elements(W.t).Any()) { - var collectionOfRuns = element.Elements() + var collectionOfRuns = element + .Elements() .Where(e => e.Name != W.rPr) .Select(e => + { + if (e.Name == W.t) { - if (e.Name == W.t) - { - var s = (string)e; - var collectionOfSubRuns = s.Select(c => - { - var newRun = new XElement(W.r, - element.Elements(W.rPr), - new XElement(W.t, - c == ' ' ? - new XAttribute(XNamespace.Xml + "space", "preserve") : - null, c)); - return newRun; - }); - return (object)collectionOfSubRuns; - } - else + var s = (string)e; + var collectionOfSubRuns = s.Select(c => { - var newRun = new XElement(W.r, + var newRun = new XElement( + W.r, element.Elements(W.rPr), - e); + new XElement( + W.t, + c == ' ' ? new XAttribute(XNamespace.Xml + "space", "preserve") : null, + c + ) + ); return newRun; - } - }); + }); + return (object)collectionOfSubRuns; + } + else + { + var newRun = new XElement(W.r, element.Elements(W.rPr), e); + return newRun; + } + }); return collectionOfRuns; } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => WmlSearchAndReplaceTransform(n, - search, replace, matchCase))); + element.Nodes().Select(n => WmlSearchAndReplaceTransform(n, search, replace, matchCase)) + ); } return node; } - private static void WmlSearchAndReplaceInXDocument(XDocument xDocument, string search, - string replace, bool matchCase) + private static void WmlSearchAndReplaceInXDocument( + XDocument xDocument, + string search, + string replace, + bool matchCase + ) { - var newRoot = (XElement)WmlSearchAndReplaceTransform(xDocument.Root, - search, replace, matchCase); + var newRoot = (XElement)WmlSearchAndReplaceTransform(xDocument.Root, search, replace, matchCase); xDocument.Elements().First().ReplaceWith(newRoot); } @@ -196,13 +213,17 @@ public static WmlDocument SearchAndReplace(WmlDocument doc, string search, strin return streamDoc.GetModifiedWmlDocument(); } - public static void SearchAndReplace(WordprocessingDocument wordDoc, string search, - string replace, bool matchCase) + public static void SearchAndReplace( + WordprocessingDocument wordDoc, + string search, + string replace, + bool matchCase + ) { if (RevisionAccepter.HasTrackedRevisions(wordDoc)) throw new InvalidDataException( - "Search and replace will not work with documents " + - "that contain revision tracking."); + "Search and replace will not work with documents " + "that contain revision tracking." + ); var xDoc = wordDoc.MainDocumentPart.DocumentSettingsPart.GetXDocument(); if (xDoc.Descendants(W.trackRevisions).Any()) throw new InvalidDataException("Revision tracking is turned on for document."); @@ -236,8 +257,7 @@ public static void SearchAndReplace(WordprocessingDocument wordDoc, string searc } } - private static object PmlReplaceTextTransform(XNode node, string search, string replace, - bool matchCase) + private static object PmlReplaceTextTransform(XNode node, string search, string replace, bool matchCase) { var element = node as XElement; if (element != null) @@ -245,13 +265,13 @@ private static object PmlReplaceTextTransform(XNode node, string search, string if (element.Name == A.p) { var contents = element.Descendants(A.t).Select(t => (string)t).StringConcatenate(); - if (contents.Contains(search) || - (!matchCase && contents.ToUpper().Contains(search.ToUpper()))) + if (contents.Contains(search) || (!matchCase && contents.ToUpper().Contains(search.ToUpper()))) { - var paragraphWithSplitRuns = new XElement(A.p, + var paragraphWithSplitRuns = new XElement( + A.p, element.Attributes(), - element.Nodes().Select(n => PmlReplaceTextTransform(n, search, - replace, matchCase))); + element.Nodes().Select(n => PmlReplaceTextTransform(n, search, replace, matchCase)) + ); var subRunArray = paragraphWithSplitRuns .Elements(A.r) .Where(e => @@ -264,16 +284,17 @@ private static object PmlReplaceTextTransform(XNode node, string search, string .ToArray(); var paragraphChildrenCount = subRunArray.Length; var matchId = 1; - foreach (var pc in subRunArray - .Take(paragraphChildrenCount - (search.Length - 1)) - .Select((c, i) => new { Child = c, Index = i, })) + foreach ( + var pc in subRunArray + .Take(paragraphChildrenCount - (search.Length - 1)) + .Select((c, i) => new { Child = c, Index = i }) + ) { var subSequence = subRunArray.SequenceAt(pc.Index).Take(search.Length); - var zipped = subSequence.PtZip(search, (pcp, c) => new - { - ParagraphChildProjection = pcp, - CharacterToCompare = c, - }); + var zipped = subSequence.PtZip( + search, + (pcp, c) => new { ParagraphChildProjection = pcp, CharacterToCompare = c } + ); var dontMatch = zipped.Any(z => { if (z.ParagraphChildProjection.Annotation() != null) @@ -282,7 +303,9 @@ private static object PmlReplaceTextTransform(XNode node, string search, string if (matchCase) b = z.ParagraphChildProjection.Value != z.CharacterToCompare.ToString(); else - b = z.ParagraphChildProjection.Value.ToUpper() != z.CharacterToCompare.ToString().ToUpper(); + b = + z.ParagraphChildProjection.Value.ToUpper() + != z.CharacterToCompare.ToString().ToUpper(); return b; }); var match = !dontMatch; @@ -308,43 +331,47 @@ private static object PmlReplaceTextTransform(XNode node, string search, string return sem.MatchId == id; }) .ToList(); - elementsToReplace.First().AddBeforeSelf( - new XElement(A.r, - elementsToReplace.First().Elements(A.rPr), - new XElement(A.t, replace))); + elementsToReplace + .First() + .AddBeforeSelf( + new XElement( + A.r, + elementsToReplace.First().Elements(A.rPr), + new XElement(A.t, replace) + ) + ); elementsToReplace.Remove(); } - var groupedAdjacentRunsWithIdenticalFormatting = - paragraphWithReplacedRuns + var groupedAdjacentRunsWithIdenticalFormatting = paragraphWithReplacedRuns .Elements() .GroupAdjacent(ce => { if (ce.Name != A.r) return "DontConsolidate"; - if (ce.Elements().Where(e => e.Name != A.rPr).Count() != 1 || - ce.Element(A.t) == null) + if (ce.Elements().Where(e => e.Name != A.rPr).Count() != 1 || ce.Element(A.t) == null) return "DontConsolidate"; if (ce.Element(A.rPr) == null) return ""; return ce.Element(A.rPr).ToString(SaveOptions.None); }); - var paragraphWithConsolidatedRuns = new XElement(A.p, + var paragraphWithConsolidatedRuns = new XElement( + A.p, groupedAdjacentRunsWithIdenticalFormatting.Select(g => { if (g.Key == "DontConsolidate") return (object)g; var textValue = g.Select(r => r.Element(A.t).Value).StringConcatenate(); - return new XElement(A.r, - g.First().Elements(A.rPr), - new XElement(A.t, textValue)); - })); + return new XElement(A.r, g.First().Elements(A.rPr), new XElement(A.t, textValue)); + }) + ); return paragraphWithConsolidatedRuns; } } if (element.Name == A.r && element.Elements(A.t).Any()) { - var collectionOfRuns = element.Elements() + var collectionOfRuns = element + .Elements() .Where(e => e.Name != A.rPr) .Select(e => { @@ -353,26 +380,24 @@ private static object PmlReplaceTextTransform(XNode node, string search, string var s = (string)e; var collectionOfSubRuns = s.Select(c => { - var newRun = new XElement(A.r, - element.Elements(A.rPr), - new XElement(A.t, c)); + var newRun = new XElement(A.r, element.Elements(A.rPr), new XElement(A.t, c)); return newRun; }); return (object)collectionOfSubRuns; } else { - var newRun = new XElement(A.r, - element.Elements(A.rPr), - e); + var newRun = new XElement(A.r, element.Elements(A.rPr), e); return newRun; } }); return collectionOfRuns; } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => PmlReplaceTextTransform(n, search, replace, matchCase))); + element.Nodes().Select(n => PmlReplaceTextTransform(n, search, replace, matchCase)) + ); } return node; } @@ -387,8 +412,7 @@ public static PmlDocument SearchAndReplace(PmlDocument doc, string search, strin return streamDoc.GetModifiedPmlDocument(); } - public static void SearchAndReplace(PresentationDocument pDoc, string search, - string replace, bool matchCase) + public static void SearchAndReplace(PresentationDocument pDoc, string search, string replace, bool matchCase) { var presentationPart = pDoc.PresentationPart; foreach (var slidePart in presentationPart.SlideParts) diff --git a/Clippit/MetricsGetter.cs b/Clippit/MetricsGetter.cs index e91ec8f6..ff9516e8 100644 --- a/Clippit/MetricsGetter.cs +++ b/Clippit/MetricsGetter.cs @@ -3,18 +3,18 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml.Linq; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Validation; -using System.Globalization; using Clippit.Excel; using Clippit.PowerPoint; using Clippit.Word; using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Experimental; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Validation; using SixLabors.Fonts; namespace Clippit @@ -93,10 +93,12 @@ public static XElement GetDocxMetrics(WmlDocument wmlDoc, MetricsGetterSettings } } } - var metrics = new XElement(H.Metrics, + var metrics = new XElement( + H.Metrics, new XAttribute(H.FileName, wmlDoc.FileName), new XAttribute(H.FileType, "WordprocessingML"), - new XAttribute(H.Error, "Unknown error, metrics not determined")); + new XAttribute(H.Error, "Unknown error, metrics not determined") + ); return metrics; } @@ -139,7 +141,7 @@ public static int GetTextWidth(FontFamily ff, FontStyle fs, decimal sz, string t { // if both regular and bold fail, then get metrics for Times New Roman // use the original FontStyle (in fs) - + //var ff2 = new FontFamily("Times New Roman"); SystemFonts.Collection.TryGet("Times New Roman", out var ff2); // TODO: test this return _getTextWidth(ff2, fs, sz, text); @@ -158,13 +160,18 @@ private static Uri FixUri(string brokenUri) return new Uri("http://broken-link/"); } - private static XElement GetWmlMetrics(string fileName, bool invalidHyperlink, WordprocessingDocument wDoc, MetricsGetterSettings settings) + private static XElement GetWmlMetrics( + string fileName, + bool invalidHyperlink, + WordprocessingDocument wDoc, + MetricsGetterSettings settings + ) { - var parts = new XElement(H.Parts, - wDoc.GetAllParts().Select(part => GetMetricsForWmlPart(part, settings))); + var parts = new XElement(H.Parts, wDoc.GetAllParts().Select(part => GetMetricsForWmlPart(part, settings))); if (!parts.HasElements) parts = null; - var metrics = new XElement(H.Metrics, + var metrics = new XElement( + H.Metrics, new XAttribute(H.FileName, fileName), new XAttribute(H.FileType, "WordprocessingML"), GetStyleHierarchy(wDoc), @@ -172,7 +179,7 @@ private static XElement GetWmlMetrics(string fileName, bool invalidHyperlink, Wo parts, settings.RetrieveNamespaceList ? RetrieveNamespaceList(wDoc) : null, settings.RetrieveContentTypeList ? RetrieveContentTypeList(wDoc) : null - ); + ); return metrics; } @@ -182,12 +189,11 @@ private static XElement RetrieveContentTypeList(OpenXmlPackage oxPkg) var nonRelationshipParts = pkg.GetParts() .Where(p => p.ContentType != "application/vnd.openxmlformats-package.relationships+xml"); - var contentTypes = nonRelationshipParts - .Select(p => p.ContentType) - .OrderBy(t => t) - .Distinct(); - var xe = new XElement(H.ContentTypes, - contentTypes.Select(ct => new XElement(H.ContentType, new XAttribute(H.Val, ct)))); + var contentTypes = nonRelationshipParts.Select(p => p.ContentType).OrderBy(t => t).Distinct(); + var xe = new XElement( + H.ContentTypes, + contentTypes.Select(ct => new XElement(H.ContentType, new XAttribute(H.Val, ct))) + ); return xe; } @@ -197,8 +203,7 @@ private static XElement RetrieveNamespaceList(OpenXmlPackage oxPkg) var nonRelationshipParts = pkg.GetParts() .Where(p => p.ContentType != "application/vnd.openxmlformats-package.relationships+xml"); - var xmlParts = nonRelationshipParts - .Where(p => p.ContentType.ToLower().EndsWith("xml")); + var xmlParts = nonRelationshipParts.Where(p => p.ContentType.ToLower().EndsWith("xml")); var uniqueNamespaces = new HashSet(); foreach (var xp in xmlParts) @@ -207,8 +212,7 @@ private static XElement RetrieveNamespaceList(OpenXmlPackage oxPkg) try { var xdoc = XDocument.Load(st); - var namespaces = xdoc - .Descendants() + var namespaces = xdoc.Descendants() .Attributes() .Where(a => a.IsNamespaceDeclaration) .Select(a => $"{a.Name.LocalName}|{a.Value}") @@ -220,18 +224,22 @@ private static XElement RetrieveNamespaceList(OpenXmlPackage oxPkg) } // if catch exception, forget about it. Just trying to get a most complete survey possible of all namespaces in all documents. // if caught exception, chances are the document is bad anyway. - catch (Exception) - { - } + catch (Exception) { } } - var xe = new XElement(H.Namespaces, - uniqueNamespaces.OrderBy(t => t).Select(n => - { - var spl = n.Split('|'); - return new XElement(H.Namespace, - new XAttribute(H.NamespacePrefix, spl[0]), - new XAttribute(H.NamespaceName, spl[1])); - })); + var xe = new XElement( + H.Namespaces, + uniqueNamespaces + .OrderBy(t => t) + .Select(n => + { + var spl = n.Split('|'); + return new XElement( + H.Namespace, + new XAttribute(H.NamespacePrefix, spl[0]), + new XAttribute(H.NamespaceName, spl[1]) + ); + }) + ); return xe; } @@ -252,17 +260,22 @@ private static List GetMiscWmlMetrics(WordprocessingDocument document, } private static readonly (FileFormatVersions, XName)[] s_validationSchemas = - { - (FileFormatVersions.Office2007, H.SdkValidationError2007), - (FileFormatVersions.Office2010, H.SdkValidationError2010), - (FileFormatVersions.Office2013, H.SdkValidationError2013), - (FileFormatVersions.Office2016, H.SdkValidationError2016), - (FileFormatVersions.Office2019, H.SdkValidationError2019), - (FileFormatVersions.Office2021, H.SdkValidationError2021), - (FileFormatVersions.Microsoft365, H.SdkValidationErrorMicrosoft365), - }; - - private static bool ValidateWordprocessingDocument(WordprocessingDocument wDoc, List metrics, List notes, Dictionary metricCountDictionary) + { + (FileFormatVersions.Office2007, H.SdkValidationError2007), + (FileFormatVersions.Office2010, H.SdkValidationError2010), + (FileFormatVersions.Office2013, H.SdkValidationError2013), + (FileFormatVersions.Office2016, H.SdkValidationError2016), + (FileFormatVersions.Office2019, H.SdkValidationError2019), + (FileFormatVersions.Office2021, H.SdkValidationError2021), + (FileFormatVersions.Microsoft365, H.SdkValidationErrorMicrosoft365), + }; + + private static bool ValidateWordprocessingDocument( + WordprocessingDocument wDoc, + List metrics, + List notes, + Dictionary metricCountDictionary + ) { var valid = false; foreach (var (fileFormatVersion, xName) in s_validationSchemas) @@ -326,14 +339,20 @@ private static bool ValidateWordprocessingDocument(WordprocessingDocument wDoc, foreach (var item in metricCountDictionary) { - metrics.Add( - new XElement(item.Key, new XAttribute(H.Val, item.Value))); + metrics.Add(new XElement(item.Key, new XAttribute(H.Val, item.Value))); } metrics.Add(new XElement(H.ElementCount, new XAttribute(H.Val, elementCount))); - metrics.Add(new XElement(H.AverageParagraphLength, new XAttribute(H.Val, (int)(textCount / (double)paragraphCount)))); - - if (wDoc.GetAllParts().Any(part => part.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) + metrics.Add( + new XElement(H.AverageParagraphLength, new XAttribute(H.Val, (int)(textCount / (double)paragraphCount))) + ); + + if ( + wDoc.GetAllParts() + .Any(part => + part.ContentType == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ) + ) metrics.Add(new XElement(H.EmbeddedXlsx, new XAttribute(H.Val, true))); NumberingFormatListAssembly(wDoc, metrics); @@ -345,11 +364,10 @@ private static bool ValidateWordprocessingDocument(WordprocessingDocument wDoc, if (d.Name == W.saveThroughXslt) { var rid = (string)d.Attribute(R.id); - var tempExternalRelationship = wDoc - .MainDocumentPart - .DocumentSettingsPart - .ExternalRelationships - .FirstOrDefault(h => h.Id == rid); + var tempExternalRelationship = + wDoc.MainDocumentPart.DocumentSettingsPart.ExternalRelationships.FirstOrDefault(h => + h.Id == rid + ); if (tempExternalRelationship == null) metrics.Add(new XElement(H.InvalidSaveThroughXslt, new XAttribute(H.Val, true))); valid = false; @@ -365,7 +383,12 @@ private static bool ValidateWordprocessingDocument(WordprocessingDocument wDoc, return valid; } - private static bool ValidateAgainstSpecificVersion(WordprocessingDocument wDoc, List metrics, FileFormatVersions versionToValidateAgainst, XName versionSpecificMetricName) + private static bool ValidateAgainstSpecificVersion( + WordprocessingDocument wDoc, + List metrics, + FileFormatVersions versionToValidateAgainst, + XName versionSpecificMetricName + ) { var validator = new OpenXmlValidator(versionToValidateAgainst); var errors = validator.Validate(wDoc); @@ -374,23 +397,40 @@ private static bool ValidateAgainstSpecificVersion(WordprocessingDocument wDoc, { if (!metrics.Any(e => e.Name == H.SdkValidationError)) metrics.Add(new XElement(H.SdkValidationError, new XAttribute(H.Val, true))); - metrics.Add(new XElement(versionSpecificMetricName, new XAttribute(H.Val, true), - errors.Take(3).Select(err => - { - var sb = new StringBuilder(); - if (err.Description.Length > 300) - sb.Append(PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + Environment.NewLine); - else - sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); - sb.Append(" in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine); - sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); - return sb.ToString(); - }))); + metrics.Add( + new XElement( + versionSpecificMetricName, + new XAttribute(H.Val, true), + errors + .Take(3) + .Select(err => + { + var sb = new StringBuilder(); + if (err.Description.Length > 300) + sb.Append( + PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + + Environment.NewLine + ); + else + sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); + sb.Append( + " in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine + ); + sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); + return sb.ToString(); + }) + ) + ); } return valid; } - private static bool ValidateAgainstSpecificVersion(SpreadsheetDocument sDoc, List metrics, FileFormatVersions versionToValidateAgainst, XName versionSpecificMetricName) + private static bool ValidateAgainstSpecificVersion( + SpreadsheetDocument sDoc, + List metrics, + FileFormatVersions versionToValidateAgainst, + XName versionSpecificMetricName + ) { var validator = new OpenXmlValidator(versionToValidateAgainst); var errors = validator.Validate(sDoc); @@ -399,23 +439,40 @@ private static bool ValidateAgainstSpecificVersion(SpreadsheetDocument sDoc, Lis { if (!metrics.Any(e => e.Name == H.SdkValidationError)) metrics.Add(new XElement(H.SdkValidationError, new XAttribute(H.Val, true))); - metrics.Add(new XElement(versionSpecificMetricName, new XAttribute(H.Val, true), - errors.Take(3).Select(err => - { - var sb = new StringBuilder(); - if (err.Description.Length > 300) - sb.Append(PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + Environment.NewLine); - else - sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); - sb.Append(" in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine); - sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); - return sb.ToString(); - }))); + metrics.Add( + new XElement( + versionSpecificMetricName, + new XAttribute(H.Val, true), + errors + .Take(3) + .Select(err => + { + var sb = new StringBuilder(); + if (err.Description.Length > 300) + sb.Append( + PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + + Environment.NewLine + ); + else + sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); + sb.Append( + " in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine + ); + sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); + return sb.ToString(); + }) + ) + ); } return valid; } - private static bool ValidateAgainstSpecificVersion(PresentationDocument pDoc, List metrics, FileFormatVersions versionToValidateAgainst, XName versionSpecificMetricName) + private static bool ValidateAgainstSpecificVersion( + PresentationDocument pDoc, + List metrics, + FileFormatVersions versionToValidateAgainst, + XName versionSpecificMetricName + ) { var validator = new OpenXmlValidator(versionToValidateAgainst); var errors = validator.Validate(pDoc); @@ -424,18 +481,30 @@ private static bool ValidateAgainstSpecificVersion(PresentationDocument pDoc, Li { if (!metrics.Any(e => e.Name == H.SdkValidationError)) metrics.Add(new XElement(H.SdkValidationError, new XAttribute(H.Val, true))); - metrics.Add(new XElement(versionSpecificMetricName, new XAttribute(H.Val, true), - errors.Take(3).Select(err => - { - var sb = new StringBuilder(); - if (err.Description.Length > 300) - sb.Append(PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + Environment.NewLine); - else - sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); - sb.Append(" in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine); - sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); - return sb.ToString(); - }))); + metrics.Add( + new XElement( + versionSpecificMetricName, + new XAttribute(H.Val, true), + errors + .Take(3) + .Select(err => + { + var sb = new StringBuilder(); + if (err.Description.Length > 300) + sb.Append( + PtUtils.MakeValidXml(err.Description.Substring(0, 300) + " ... elided ...") + + Environment.NewLine + ); + else + sb.Append(PtUtils.MakeValidXml(err.Description) + Environment.NewLine); + sb.Append( + " in part " + PtUtils.MakeValidXml(err.Part.Uri.ToString()) + Environment.NewLine + ); + sb.Append(" at " + PtUtils.MakeValidXml(err.Path.XPath) + Environment.NewLine); + return sb.ToString(); + }) + ) + ); } return valid; } @@ -455,34 +524,47 @@ private static void ValidateImageExists(OpenXmlPart part, string relId, Dictiona IncrementMetric(metrics, H.ReferenceToNullImage); } - private static void NumberingFormatListAssembly(WordprocessingDocument wDoc, List metrics) { var numFmtList = new List(); foreach (var part in wDoc.ContentParts()) { var xDoc = part.GetXDocument(); - numFmtList = numFmtList.Concat(xDoc - .Descendants(W.p) - .Select(p => - { - ListItemRetriever.RetrieveListItem(wDoc, p, null); - var lif = p.Annotation(); - if (lif != null && lif.IsListItem && lif.Lvl(ListItemRetriever.GetParagraphLevel(p)) != null) - { - var numFmtForLevel = (string)lif.Lvl(ListItemRetriever.GetParagraphLevel(p)).Elements(W.numFmt).Attributes(W.val).FirstOrDefault(); - if (numFmtForLevel == null) + numFmtList = numFmtList + .Concat( + xDoc.Descendants(W.p) + .Select(p => { - var numFmtElement = lif.Lvl(ListItemRetriever.GetParagraphLevel(p)).Elements(MC.AlternateContent).Elements(MC.Choice).Elements(W.numFmt).FirstOrDefault(); - if (numFmtElement != null && (string)numFmtElement.Attribute(W.val) == "custom") - numFmtForLevel = (string)numFmtElement.Attribute(W.format); - } - return numFmtForLevel; - } - return null; - }) - .Where(s => s != null) - .Distinct()) + ListItemRetriever.RetrieveListItem(wDoc, p, null); + var lif = p.Annotation(); + if ( + lif != null + && lif.IsListItem + && lif.Lvl(ListItemRetriever.GetParagraphLevel(p)) != null + ) + { + var numFmtForLevel = (string) + lif.Lvl(ListItemRetriever.GetParagraphLevel(p)) + .Elements(W.numFmt) + .Attributes(W.val) + .FirstOrDefault(); + if (numFmtForLevel == null) + { + var numFmtElement = lif.Lvl(ListItemRetriever.GetParagraphLevel(p)) + .Elements(MC.AlternateContent) + .Elements(MC.Choice) + .Elements(W.numFmt) + .FirstOrDefault(); + if (numFmtElement != null && (string)numFmtElement.Attribute(W.val) == "custom") + numFmtForLevel = (string)numFmtElement.Attribute(W.format); + } + return numFmtForLevel; + } + return null; + }) + .Where(s => s != null) + .Distinct() + ) .ToList(); } if (numFmtList.Any()) @@ -517,7 +599,11 @@ public FormattingMetrics() } } - private static void FontAndCharSetAnalysis(WordprocessingDocument wDoc, List metrics, List notes) + private static void FontAndCharSetAnalysis( + WordprocessingDocument wDoc, + List metrics, + List notes + ) { var settings = new FormattingAssemblerSettings { @@ -541,7 +627,9 @@ private static void FontAndCharSetAnalysis(WordprocessingDocument wDoc, List 0) - metrics.Add(new XElement(H.RunWithoutRprCount, new XAttribute(H.Val, formattingMetrics.RunWithoutRprCount))); + metrics.Add( + new XElement(H.RunWithoutRprCount, new XAttribute(H.Val, formattingMetrics.RunWithoutRprCount)) + ); if (formattingMetrics.ZeroLengthText > 0) metrics.Add(new XElement(H.ZeroLengthText, new XAttribute(H.Val, formattingMetrics.ZeroLengthText))); if (formattingMetrics.MultiFontRun > 0) @@ -551,7 +639,9 @@ private static void FontAndCharSetAnalysis(WordprocessingDocument wDoc, List 0) metrics.Add(new XElement(H.CSCharCount, new XAttribute(H.Val, formattingMetrics.CSCharCount))); if (formattingMetrics.EastAsiaCharCount > 0) - metrics.Add(new XElement(H.EastAsiaCharCount, new XAttribute(H.Val, formattingMetrics.EastAsiaCharCount))); + metrics.Add( + new XElement(H.EastAsiaCharCount, new XAttribute(H.Val, formattingMetrics.EastAsiaCharCount)) + ); if (formattingMetrics.HAnsiCharCount > 0) metrics.Add(new XElement(H.HAnsiCharCount, new XAttribute(H.Val, formattingMetrics.HAnsiCharCount))); if (formattingMetrics.AsciiRunCount > 0) @@ -559,7 +649,9 @@ private static void FontAndCharSetAnalysis(WordprocessingDocument wDoc, List 0) metrics.Add(new XElement(H.CSRunCount, new XAttribute(H.Val, formattingMetrics.CSRunCount))); if (formattingMetrics.EastAsiaRunCount > 0) - metrics.Add(new XElement(H.EastAsiaRunCount, new XAttribute(H.Val, formattingMetrics.EastAsiaRunCount))); + metrics.Add( + new XElement(H.EastAsiaRunCount, new XAttribute(H.Val, formattingMetrics.EastAsiaRunCount)) + ); if (formattingMetrics.HAnsiRunCount > 0) metrics.Add(new XElement(H.HAnsiRunCount, new XAttribute(H.Val, formattingMetrics.HAnsiRunCount))); @@ -570,7 +662,13 @@ private static void FontAndCharSetAnalysis(WordprocessingDocument wDoc, List attList, List notes, FormattingMetrics formattingMetrics, string uri) + private static void AnalyzeRun( + XElement run, + List attList, + List notes, + FormattingMetrics formattingMetrics, + string uri + ) { var runText = run.Elements() .Where(e => e.Name == W.t || e.Name == W.delText) @@ -592,9 +690,7 @@ private static void AnalyzeRun(XElement run, List attList, List FormattingAssembler.DetermineFontTypeFromCharacter(ch, csa)) .ToArray(); - var distinctFontTypeArray = fontTypeArray - .Distinct() - .ToArray(); + var distinctFontTypeArray = fontTypeArray.Distinct().ToArray(); var distinctFonts = distinctFontTypeArray .Select(ft => { @@ -609,14 +705,15 @@ private static void AnalyzeRun(XElement run, List attList, List csa.LatinLang, FormattingAssembler.FontType.CS => csa.BidiLang, FormattingAssembler.FontType.EastAsia => csa.EastAsiaLang, - _ => csa.LatinLang + _ => csa.LatinLang, }; //if (ft == FormattingAssembler.FontType.HAnsi) }) .Select(l => { if (l is "" or null) - return /* "Dflt:" + */ CultureInfo.CurrentCulture.Name; + return /* "Dflt:" + */ + CultureInfo.CurrentCulture.Name; return l; }) //.Where(l => l != null && l != "") @@ -628,10 +725,18 @@ private static void AnalyzeRun(XElement run, List attList, List ft == FormattingAssembler.FontType.Ascii).Count(); - formattingMetrics.CSCharCount += fontTypeArray.Where(ft => ft == FormattingAssembler.FontType.CS).Count(); - formattingMetrics.EastAsiaCharCount += fontTypeArray.Where(ft => ft == FormattingAssembler.FontType.EastAsia).Count(); - formattingMetrics.HAnsiCharCount += fontTypeArray.Where(ft => ft == FormattingAssembler.FontType.HAnsi).Count(); + formattingMetrics.AsciiCharCount += fontTypeArray + .Where(ft => ft == FormattingAssembler.FontType.Ascii) + .Count(); + formattingMetrics.CSCharCount += fontTypeArray + .Where(ft => ft == FormattingAssembler.FontType.CS) + .Count(); + formattingMetrics.EastAsiaCharCount += fontTypeArray + .Where(ft => ft == FormattingAssembler.FontType.EastAsia) + .Count(); + formattingMetrics.HAnsiCharCount += fontTypeArray + .Where(ft => ft == FormattingAssembler.FontType.HAnsi) + .Count(); } else { @@ -657,7 +762,10 @@ private static void AnalyzeRun(XElement run, List attList, List csa.CsFont, FormattingAssembler.FontType.EastAsia => csa.EastAsiaFont, FormattingAssembler.FontType.HAnsi => csa.HAnsiFont, - _ => csa.AsciiFont + _ => csa.AsciiFont, }; } @@ -681,23 +789,24 @@ public static XElement GetXlsxMetrics(SmlDocument smlDoc, MetricsGetterSettings valid |= ValidateAgainstSpecificVersion(sDoc, metrics, fileFormatVersion, xName); } - return new XElement(H.Metrics, + return new XElement( + H.Metrics, new XAttribute(H.FileName, smlDoc.FileName), new XAttribute(H.FileType, "SpreadsheetML"), metrics, GetTableInfoForWorkbook(sDoc, settings), settings.RetrieveNamespaceList ? RetrieveNamespaceList(sDoc) : null, - settings.RetrieveContentTypeList ? RetrieveContentTypeList(sDoc) : null); + settings.RetrieveContentTypeList ? RetrieveContentTypeList(sDoc) : null + ); } private static XElement GetTableInfoForWorkbook(SpreadsheetDocument spreadsheet, MetricsGetterSettings settings) { var workbookPart = spreadsheet.WorkbookPart; var xd = workbookPart.GetXDocument(); - var partInformation = - new XElement(H.Sheets, - xd.Root - .Element(S.sheets) + var partInformation = new XElement( + H.Sheets, + xd.Root.Element(S.sheets) .Elements(S.sheet) .Select(sh => { @@ -705,17 +814,25 @@ private static XElement GetTableInfoForWorkbook(SpreadsheetDocument spreadsheet, var sheetName = (string)sh.Attribute("name"); var worksheetPart = (WorksheetPart)workbookPart.GetPartById(rid); return GetTableInfoForSheet(spreadsheet, worksheetPart, sheetName, settings); - })); + }) + ); return partInformation; } - public static XElement GetTableInfoForSheet(SpreadsheetDocument spreadsheetDocument, WorksheetPart sheetPart, string sheetName, - MetricsGetterSettings settings) + public static XElement GetTableInfoForSheet( + SpreadsheetDocument spreadsheetDocument, + WorksheetPart sheetPart, + string sheetName, + MetricsGetterSettings settings + ) { var xd = sheetPart.GetXDocument(); - var sheetInformation = new XElement(H.Sheet, - new XAttribute(H.Name, sheetName), - xd.Root.Elements(S.tableParts).Elements(S.tablePart).Select(tp => + var sheetInformation = new XElement( + H.Sheet, + new XAttribute(H.Name, sheetName), + xd.Root.Elements(S.tableParts) + .Elements(S.tablePart) + .Select(tp => { var rId = (string)tp.Attribute(R.id); var tablePart = (TableDefinitionPart)sheetPart.GetPartById(rId); @@ -725,33 +842,48 @@ public static XElement GetTableInfoForSheet(SpreadsheetDocument spreadsheetDocum if (settings.IncludeXlsxTableCellData) { var xlsxTable = spreadsheetDocument.Table(tableName); - tableCellData = new XElement(H.TableData, - xlsxTable.TableRows() + tableCellData = new XElement( + H.TableData, + xlsxTable + .TableRows() .Select(row => { - var rowElement = new XElement(H.Row, - xlsxTable.TableColumns().Select(col => - { - var cellElement = new XElement(H.Cell, - new XAttribute(H.Name, col.Name), - new XAttribute(H.Val, (string)row[col.Name])); - return cellElement; - })); + var rowElement = new XElement( + H.Row, + xlsxTable + .TableColumns() + .Select(col => + { + var cellElement = new XElement( + H.Cell, + new XAttribute(H.Name, col.Name), + new XAttribute(H.Val, (string)row[col.Name]) + ); + return cellElement; + }) + ); return rowElement; - })); + }) + ); } - var table = new XElement(H.Table, + var table = new XElement( + H.Table, new XAttribute(H.Name, (string)txd.Root.Attribute("name")), new XAttribute(H.DisplayName, tableName), - new XElement(H.Columns, - txd.Root.Element(S.tableColumns).Elements(S.tableColumn) - .Select(tc => new XElement(H.Column, - new XAttribute(H.Name, (string)tc.Attribute("name"))))), - tableCellData - ); + new XElement( + H.Columns, + txd.Root.Element(S.tableColumns) + .Elements(S.tableColumn) + .Select(tc => new XElement( + H.Column, + new XAttribute(H.Name, (string)tc.Attribute("name")) + )) + ), + tableCellData + ); return table; }) - ); + ); if (!sheetInformation.HasElements) return null; return sheetInformation; @@ -769,12 +901,14 @@ public static XElement GetPptxMetrics(PmlDocument pmlDoc, MetricsGetterSettings valid |= ValidateAgainstSpecificVersion(pDoc, metrics, fileFormatVersion, xName); } - return new XElement(H.Metrics, + return new XElement( + H.Metrics, new XAttribute(H.FileName, pmlDoc.FileName), new XAttribute(H.FileType, "PresentationML"), metrics, settings.RetrieveNamespaceList ? RetrieveNamespaceList(pDoc) : null, - settings.RetrieveContentTypeList ? RetrieveContentTypeList(pDoc) : null); + settings.RetrieveContentTypeList ? RetrieveContentTypeList(pDoc) : null + ); } private static object GetStyleHierarchy(WordprocessingDocument document) @@ -783,8 +917,8 @@ private static object GetStyleHierarchy(WordprocessingDocument document) if (stylePart == null) return null; var xd = stylePart.GetXDocument(); - var stylesWithPath = xd.Root - .Elements(W.style) + var stylesWithPath = xd + .Root.Elements(W.style) .Select(s => { var styleString = (string)s.Attribute(W.styleId); @@ -795,7 +929,9 @@ private static object GetStyleHierarchy(WordprocessingDocument document) if (baseStyle == null) break; styleString = baseStyle + "/" + styleString; - thisStyle = xd.Root.Elements(W.style).FirstOrDefault(ts => ts.Attribute(W.styleId).Value == baseStyle); + thisStyle = xd + .Root.Elements(W.style) + .FirstOrDefault(ts => ts.Attribute(W.styleId).Value == baseStyle); if (thisStyle == null) break; } @@ -809,12 +945,24 @@ private static object GetStyleHierarchy(WordprocessingDocument document) var styleChain = item.Split('/'); var elementToAddTo = styleHierarchy; foreach (var inChain in styleChain.SkipLast(1)) - elementToAddTo = elementToAddTo.Elements(H.Style).FirstOrDefault(z => z.Attribute(H.Id).Value == inChain); + elementToAddTo = elementToAddTo + .Elements(H.Style) + .FirstOrDefault(z => z.Attribute(H.Id).Value == inChain); var styleToAdd = styleChain.Last(); elementToAddTo.Add( - new XElement(H.Style, + new XElement( + H.Style, new XAttribute(H.Id, styleChain.Last()), - new XAttribute(H.Type, (string)xd.Root.Elements(W.style).First(z => z.Attribute(W.styleId).Value == styleToAdd).Attribute(W.type)))); + new XAttribute( + H.Type, + (string) + xd + .Root.Elements(W.style) + .First(z => z.Attribute(W.styleId).Value == styleToAdd) + .Attribute(W.type) + ) + ) + ); } return styleHierarchy; } @@ -829,10 +977,12 @@ private static XElement GetMetricsForWmlPart(OpenXmlPart part, MetricsGetterSett if (!contentControls.HasElements) contentControls = null; } - var partMetrics = new XElement(H.Part, + var partMetrics = new XElement( + H.Part, new XAttribute(H.ContentType, part.ContentType), new XAttribute(H.Uri, part.Uri.ToString()), - contentControls); + contentControls + ); if (partMetrics.HasElements) return partMetrics; return null; @@ -844,8 +994,10 @@ private static object GetContentControlsTransform(XNode node, MetricsGetterSetti if (element != null) { if (element == element.Document.Root) - return new XElement(H.ContentControls, - element.Nodes().Select(n => GetContentControlsTransform(n, settings))); + return new XElement( + H.ContentControls, + element.Nodes().Select(n => GetContentControlsTransform(n, settings)) + ); if (element.Name == W.sdt) { @@ -868,39 +1020,56 @@ private static object GetContentControlsTransform(XNode node, MetricsGetterSetti var isEquation = element.Elements(W.sdtPr).Elements(W.equation).Any(); var isGroup = element.Elements(W.sdtPr).Elements(W.group).Any(); var isPicture = element.Elements(W.sdtPr).Elements(W.picture).Any(); - var isRichText = element.Elements(W.sdtPr).Elements(W.richText).Any() || - (! isText && - ! isBibliography && - ! isCitation && - ! isComboBox && - ! isDate && - ! isDocPartList && - ! isDocPartObj && - ! isDropDownList && - ! isEquation && - ! isGroup && - ! isPicture); + var isRichText = + element.Elements(W.sdtPr).Elements(W.richText).Any() + || ( + !isText + && !isBibliography + && !isCitation + && !isComboBox + && !isDate + && !isDocPartList + && !isDocPartObj + && !isDropDownList + && !isEquation + && !isGroup + && !isPicture + ); string type = null; - if (isText ) type = "Text"; - if (isBibliography) type = "Bibliography"; - if (isCitation ) type = "Citation"; - if (isComboBox ) type = "ComboBox"; - if (isDate ) type = "Date"; - if (isDocPartList ) type = "DocPartList"; - if (isDocPartObj ) type = "DocPartObj"; - if (isDropDownList) type = "DropDownList"; - if (isEquation ) type = "Equation"; - if (isGroup ) type = "Group"; - if (isPicture ) type = "Picture"; - if (isRichText ) type = "RichText"; + if (isText) + type = "Text"; + if (isBibliography) + type = "Bibliography"; + if (isCitation) + type = "Citation"; + if (isComboBox) + type = "ComboBox"; + if (isDate) + type = "Date"; + if (isDocPartList) + type = "DocPartList"; + if (isDocPartObj) + type = "DocPartObj"; + if (isDropDownList) + type = "DropDownList"; + if (isEquation) + type = "Equation"; + if (isGroup) + type = "Group"; + if (isPicture) + type = "Picture"; + if (isRichText) + type = "RichText"; var typeAttr = new XAttribute(H.Type, type); - return new XElement(H.ContentControl, + return new XElement( + H.ContentControl, typeAttr, tagAttr, aliasAttr, xPathAttr, - element.Nodes().Select(n => GetContentControlsTransform(n, settings))); + element.Nodes().Select(n => GetContentControlsTransform(n, settings)) + ); } return element.Nodes().Select(n => GetContentControlsTransform(n, settings)); diff --git a/Clippit/OpenXmlRegex.cs b/Clippit/OpenXmlRegex.cs index 35fa4dc1..ed011501 100644 --- a/Clippit/OpenXmlRegex.cs +++ b/Clippit/OpenXmlRegex.cs @@ -13,35 +13,36 @@ public class OpenXmlRegex { private const string DontConsolidate = "DontConsolidate"; - private static readonly HashSet RevTrackMarkupWithId = new() - { - W.cellDel, - W.cellIns, - W.cellMerge, - W.customXmlDelRangeEnd, - W.customXmlDelRangeStart, - W.customXmlInsRangeEnd, - W.customXmlInsRangeStart, - W.customXmlMoveFromRangeEnd, - W.customXmlMoveFromRangeStart, - W.customXmlMoveToRangeEnd, - W.customXmlMoveToRangeStart, - W.del, - W.ins, - W.moveFrom, - W.moveFromRangeEnd, - W.moveFromRangeStart, - W.moveTo, - W.moveToRangeEnd, - W.moveToRangeStart, - W.pPrChange, - W.rPrChange, - W.sectPrChange, - W.tblGridChange, - W.tblPrChange, - W.tblPrExChange, - W.tcPrChange - }; + private static readonly HashSet RevTrackMarkupWithId = + new() + { + W.cellDel, + W.cellIns, + W.cellMerge, + W.customXmlDelRangeEnd, + W.customXmlDelRangeStart, + W.customXmlInsRangeEnd, + W.customXmlInsRangeStart, + W.customXmlMoveFromRangeEnd, + W.customXmlMoveFromRangeStart, + W.customXmlMoveToRangeEnd, + W.customXmlMoveToRangeStart, + W.del, + W.ins, + W.moveFrom, + W.moveFromRangeEnd, + W.moveFromRangeStart, + W.moveTo, + W.moveToRangeEnd, + W.moveToRangeStart, + W.pPrChange, + W.rPrChange, + W.sectPrChange, + W.tblGridChange, + W.tblPrChange, + W.tblPrExChange, + W.tcPrChange, + }; public static int Match(IEnumerable content, Regex regex) { @@ -54,13 +55,20 @@ public static int Match(IEnumerable content, Regex regex) /// public static int Match(IEnumerable content, Regex regex, Action found) { - return ReplaceInternal(content, regex, null, + return ReplaceInternal( + content, + regex, + null, (x, m) => { - if (found != null) found.Invoke(x, m); + if (found != null) + found.Invoke(x, m); return true; }, - false, null, true); + false, + null, + true + ); } /// @@ -74,8 +82,12 @@ public static int Match(IEnumerable content, Regex regex, Action - public static int Replace(IEnumerable content, Regex regex, string replacement, - Func doReplacement) + public static int Replace( + IEnumerable content, + Regex regex, + string replacement, + Func doReplacement + ) { return ReplaceInternal(content, regex, replacement, doReplacement, false, null, true); } @@ -83,8 +95,13 @@ public static int Replace(IEnumerable content, Regex regex, string rep /// /// This overload enables not coalescing content, which is necessary for DocumentAssembler. /// - public static int Replace(IEnumerable content, Regex regex, string replacement, - Func doReplacement, bool coalesceContent) + public static int Replace( + IEnumerable content, + Regex regex, + string replacement, + Func doReplacement, + bool coalesceContent + ) { return ReplaceInternal(content, regex, replacement, doReplacement, false, null, coalesceContent); } @@ -104,18 +121,32 @@ public static int Replace(IEnumerable content, Regex regex, string rep /// If trackRevisions == true for a PPTX /// Then code throws an exception /// - public static int Replace(IEnumerable content, Regex regex, string replacement, - Func doReplacement, bool trackRevisions, string author) + public static int Replace( + IEnumerable content, + Regex regex, + string replacement, + Func doReplacement, + bool trackRevisions, + string author + ) { return ReplaceInternal(content, regex, replacement, doReplacement, trackRevisions, author, true); } - private static int ReplaceInternal(IEnumerable content, Regex regex, string replacement, - Func callback, bool trackRevisions, string revisionTrackingAuthor, - bool coalesceContent) + private static int ReplaceInternal( + IEnumerable content, + Regex regex, + string replacement, + Func callback, + bool trackRevisions, + string revisionTrackingAuthor, + bool coalesceContent + ) { - if (content == null) throw new ArgumentNullException(nameof(content)); - if (regex == null) throw new ArgumentNullException(nameof(regex)); + if (content == null) + throw new ArgumentNullException(nameof(content)); + if (regex == null) + throw new ArgumentNullException(nameof(regex)); IEnumerable contentList = content as IList ?? content.ToList(); @@ -131,38 +162,47 @@ private static int ReplaceInternal(IEnumerable content, Regex regex, s var replInfo = new ReplaceInternalInfo { Count = 0 }; foreach (var c in contentList) { - var newC = (XElement) WmlSearchAndReplaceTransform(c, regex, replacement, callback, trackRevisions, - revisionTrackingAuthor, replInfo, coalesceContent); + var newC = (XElement)WmlSearchAndReplaceTransform( + c, + regex, + replacement, + callback, + trackRevisions, + revisionTrackingAuthor, + replInfo, + coalesceContent + ); c.ReplaceNodes(newC.Nodes()); } var root = contentList.First().AncestorsAndSelf().Last(); - var nextId = new[] { 0 } - .Concat(root - .Descendants() - .Where(d => RevTrackMarkupWithId.Contains(d.Name)) - .Attributes(W.id) - .Select(a => (int) a)) - .Max() + 1; - var revTrackingWithoutId = root - .DescendantsAndSelf() + var nextId = + new[] { 0 } + .Concat( + root.Descendants() + .Where(d => RevTrackMarkupWithId.Contains(d.Name)) + .Attributes(W.id) + .Select(a => (int)a) + ) + .Max() + 1; + var revTrackingWithoutId = root.DescendantsAndSelf() .Where(d => RevTrackMarkupWithId.Contains(d.Name) && (d.Attribute(W.id) == null)); foreach (var item in revTrackingWithoutId) item.Add(new XAttribute(W.id, nextId++)); - var revTrackingWithDuplicateIds = root - .DescendantsAndSelf() + var revTrackingWithDuplicateIds = root.DescendantsAndSelf() .Where(d => RevTrackMarkupWithId.Contains(d.Name)) - .GroupBy(d => (int) d.Attribute(W.id)) + .GroupBy(d => (int)d.Attribute(W.id)) .Where(g => g.Count() > 1) .ToList(); foreach (var group in revTrackingWithDuplicateIds) - foreach (var gc in group.Skip(1)) - { - var xAttribute = gc.Attribute(W.id); - if (xAttribute != null) xAttribute.Value = nextId.ToString(); - nextId++; - } + foreach (var gc in group.Skip(1)) + { + var xAttribute = gc.Attribute(W.id); + if (xAttribute != null) + xAttribute.Value = nextId.ToString(); + nextId++; + } return replInfo.Count; } @@ -175,7 +215,7 @@ private static int ReplaceInternal(IEnumerable content, Regex regex, s var counter = new ReplaceInternalInfo { Count = 0 }; foreach (var c in contentList) { - var newC = (XElement) PmlSearchAndReplaceTransform(c, regex, replacement, callback, counter); + var newC = (XElement)PmlSearchAndReplaceTransform(c, regex, replacement, callback, counter); c.ReplaceNodes(newC.Nodes()); } @@ -185,12 +225,20 @@ private static int ReplaceInternal(IEnumerable content, Regex regex, s return 0; } - private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, string replacement, - Func callback, bool trackRevisions, string revisionTrackingAuthor, - ReplaceInternalInfo replInfo, bool coalesceContent) + private static object WmlSearchAndReplaceTransform( + XNode node, + Regex regex, + string replacement, + Func callback, + bool trackRevisions, + string revisionTrackingAuthor, + ReplaceInternalInfo replInfo, + bool coalesceContent + ) { var element = node as XElement; - if (element == null) return node; + if (element == null) + return node; if (element.Name == W.p) { @@ -203,22 +251,34 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri .StringConcatenate(); if (regex.IsMatch(preliminaryContent)) { - var paragraphWithSplitRuns = new XElement(W.p, + var paragraphWithSplitRuns = new XElement( + W.p, paragraph.Attributes(), - paragraph.Nodes().Select(n => WmlSearchAndReplaceTransform(n, regex, replacement, callback, - trackRevisions, revisionTrackingAuthor, replInfo, coalesceContent))); + paragraph + .Nodes() + .Select(n => + WmlSearchAndReplaceTransform( + n, + regex, + replacement, + callback, + trackRevisions, + revisionTrackingAuthor, + replInfo, + coalesceContent + ) + ) + ); var runsTrimmed = paragraphWithSplitRuns .DescendantsTrimmed(W.txbxContent) .Where(d => d.Name == W.r && (d.Parent == null || d.Parent.Name != W.del)); - var charsAndRuns = runsTrimmed - .Select(r => new { Ch = UnicodeMapper.RunToString(r), r }) - .ToList(); + var charsAndRuns = runsTrimmed.Select(r => new { Ch = UnicodeMapper.RunToString(r), r }).ToList(); var content = charsAndRuns // each run should take some space in content to be able to be covered by regex and replaced/deleted - .Select(t => string.IsNullOrEmpty(t.Ch) ? " " : t.Ch) + .Select(t => string.IsNullOrEmpty(t.Ch) ? " " : t.Ch) .StringConcatenate(); var alignedRuns = charsAndRuns.Select(t => t.r).ToArray(); @@ -228,7 +288,8 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri // Process Match if (replacement == null) { - if (callback == null) return paragraph; + if (callback == null) + return paragraph; foreach (var match in matchCollection.Cast()) callback(paragraph, match); @@ -239,13 +300,12 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri // Process Replace foreach (var match in matchCollection.Cast()) { - if (match.Length == 0) continue; - if ((callback != null) && !callback(paragraph, match)) continue; + if (match.Length == 0) + continue; + if ((callback != null) && !callback(paragraph, match)) + continue; - var runCollection = alignedRuns - .Skip(match.Index) - .Take(match.Length) - .ToList(); + var runCollection = alignedRuns.Skip(match.Index).Take(match.Length).ToList(); // uses the Skip / Take special semantics of array to implement efficient finding of sub array @@ -262,12 +322,13 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri // will try to find the replacement string even though they // set coalesceContent to false. var newTextValue = match.Result(replacement); - var newRuns = UnicodeMapper.StringToCoalescedRunList(newTextValue, - firstRunProperties); - var newIns = new XElement(W.ins, + var newRuns = UnicodeMapper.StringToCoalescedRunList(newTextValue, firstRunProperties); + var newIns = new XElement( + W.ins, new XAttribute(W.author, revisionTrackingAuthor), new XAttribute(W.date, DateTime.UtcNow.ToString("s") + "Z"), - newRuns); + newRuns + ); if (firstRun.Parent != null && firstRun.Parent.Name == W.ins) firstRun.Parent.AddBeforeSelf(newIns); @@ -284,8 +345,10 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri var grandParentParagraph = parentIns.Parent; if (grandParentParagraph != null) { - if ((string) parentIns.Attributes(W.author).FirstOrDefault() == - revisionTrackingAuthor) + if ( + (string)parentIns.Attributes(W.author).FirstOrDefault() + == revisionTrackingAuthor + ) { var parentInsSiblings = grandParentParagraph .Elements() @@ -297,14 +360,23 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri { var parentInsSiblings = grandParentParagraph .Elements() - .Select(c => c == parentIns - ? new XElement(W.ins, - parentIns.Attributes(), - new XElement(W.del, - new XAttribute(W.author, revisionTrackingAuthor), - new XAttribute(W.date, DateTime.UtcNow.ToString("s") + "Z"), - parentIns.Elements().Select(TransformToDelText))) - : c) + .Select(c => + c == parentIns + ? new XElement( + W.ins, + parentIns.Attributes(), + new XElement( + W.del, + new XAttribute(W.author, revisionTrackingAuthor), + new XAttribute( + W.date, + DateTime.UtcNow.ToString("s") + "Z" + ), + parentIns.Elements().Select(TransformToDelText) + ) + ) + : c + ) .ToList(); grandParentParagraph.ReplaceNodes(parentInsSiblings); } @@ -312,10 +384,12 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri } else { - var delRun = new XElement(W.del, + var delRun = new XElement( + W.del, new XAttribute(W.author, revisionTrackingAuthor), new XAttribute(W.date, DateTime.UtcNow.ToString("s") + "Z"), - TransformToDelText(run)); + TransformToDelText(run) + ); run.ReplaceWith(delRun); } } @@ -332,8 +406,7 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri // will try to find the replacement string even though they // set coalesceContent to false. var newTextValue = match.Result(replacement); - var newRuns = UnicodeMapper.StringToCoalescedRunList(newTextValue, - firstRunProperties); + var newRuns = UnicodeMapper.StringToCoalescedRunList(newTextValue, firstRunProperties); if (firstRun.Parent != null && firstRun.Parent.Name == W.ins) firstRun.Parent.ReplaceWith(newRuns); else @@ -346,23 +419,36 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri : paragraphWithSplitRuns; } - var newParagraph = new XElement(W.p, + var newParagraph = new XElement( + W.p, paragraph.Attributes(), - paragraph.Nodes().Select(n => - { - var e = n as XElement; - if (e == null) return n; - - if (e.Name == W.pPr) - return e; - if (((e.Name == W.r) && e.Elements(W.t).Any()) || e.Elements(W.tab).Any()) - return e; - if ((e.Name == W.ins) && e.Elements(W.r).Elements(W.t).Any()) - return e; - - return WmlSearchAndReplaceTransform(e, regex, replacement, callback, - trackRevisions, revisionTrackingAuthor, replInfo, coalesceContent); - })); + paragraph + .Nodes() + .Select(n => + { + var e = n as XElement; + if (e == null) + return n; + + if (e.Name == W.pPr) + return e; + if (((e.Name == W.r) && e.Elements(W.t).Any()) || e.Elements(W.tab).Any()) + return e; + if ((e.Name == W.ins) && e.Elements(W.r).Elements(W.t).Any()) + return e; + + return WmlSearchAndReplaceTransform( + e, + regex, + replacement, + callback, + trackRevisions, + revisionTrackingAuthor, + replInfo, + coalesceContent + ); + }) + ); return coalesceContent ? WordprocessingMLUtil.CoalesceAdjacentRunsWithIdenticalFormatting(newParagraph) // CoalesceContent(newParagraph) : newParagraph; @@ -372,8 +458,18 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri { var collectionOfCollections = element .Elements() - .Select(n => WmlSearchAndReplaceTransform(n, regex, replacement, callback, trackRevisions, - revisionTrackingAuthor, replInfo, coalesceContent)) + .Select(n => + WmlSearchAndReplaceTransform( + n, + regex, + replacement, + callback, + trackRevisions, + revisionTrackingAuthor, + replInfo, + coalesceContent + ) + ) .ToList(); var collectionOfIns = collectionOfCollections .Select(c => @@ -389,66 +485,84 @@ private static object WmlSearchAndReplaceTransform(XNode node, Regex regex, stri if (element.Name == W.r) { - return element.Elements() + return element + .Elements() .Where(e => e.Name != W.rPr) - .Select(e => e.Name == W.t - ? ((string) e).Select(c => - new XElement(W.r, + .Select(e => + e.Name == W.t + ? ((string)e).Select(c => new XElement( + W.r, element.Elements(W.rPr), - new XElement(W.t, XmlUtil.GetXmlSpaceAttribute(c), c))) - : new[] { new XElement(W.r, element.Elements(W.rPr), e) }) + new XElement(W.t, XmlUtil.GetXmlSpaceAttribute(c), c) + )) + : new[] { new XElement(W.r, element.Elements(W.rPr), e) } + ) .SelectMany(t => t); } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes() - .Select(n => WmlSearchAndReplaceTransform(n, regex, replacement, callback, trackRevisions, - revisionTrackingAuthor, replInfo, coalesceContent))); + element + .Nodes() + .Select(n => + WmlSearchAndReplaceTransform( + n, + regex, + replacement, + callback, + trackRevisions, + revisionTrackingAuthor, + replInfo, + coalesceContent + ) + ) + ); } private static object TransformToDelText(XNode node) { var element = node as XElement; - if (element == null) return node; + if (element == null) + return node; if (element.Name == W.t) - return new XElement(W.delText, - XmlUtil.GetXmlSpaceAttribute(element.Value), - element.Value); + return new XElement(W.delText, XmlUtil.GetXmlSpaceAttribute(element.Value), element.Value); - return new XElement(element.Name, - element.Attributes(), - element.Nodes().Select(TransformToDelText)); + return new XElement(element.Name, element.Attributes(), element.Nodes().Select(TransformToDelText)); } - private static object PmlSearchAndReplaceTransform(XNode node, Regex regex, string replacement, - Func callback, ReplaceInternalInfo counter) + private static object PmlSearchAndReplaceTransform( + XNode node, + Regex regex, + string replacement, + Func callback, + ReplaceInternalInfo counter + ) { var element = node as XElement; - if (element == null) return node; + if (element == null) + return node; if (element.Name == A.p) { var paragraph = element; - var contents = element.Descendants(A.t).Select(t => (string) t).StringConcatenate(); + var contents = element.Descendants(A.t).Select(t => (string)t).StringConcatenate(); if (!regex.IsMatch(contents)) return new XElement(element.Name, element.Attributes(), element.Nodes()); - var paragraphWithSplitRuns = new XElement(A.p, + var paragraphWithSplitRuns = new XElement( + A.p, paragraph.Attributes(), - paragraph.Nodes() - .Select(n => PmlSearchAndReplaceTransform(n, regex, replacement, callback, counter))); + paragraph + .Nodes() + .Select(n => PmlSearchAndReplaceTransform(n, regex, replacement, callback, counter)) + ); - var runsTrimmed = paragraphWithSplitRuns - .Descendants(A.r) - .ToList(); + var runsTrimmed = paragraphWithSplitRuns.Descendants(A.r).ToList(); var charsAndRuns = runsTrimmed - .Select(r => - r.Element(A.t) != null - ? new { Ch = r.Element(A.t).Value, r } - : new { Ch = "\x01", r }) + .Select(r => r.Element(A.t) != null ? new { Ch = r.Element(A.t).Value, r } : new { Ch = "\x01", r }) .ToList(); var content = charsAndRuns.Select(t => t.Ch).StringConcatenate(); @@ -465,12 +579,10 @@ private static object PmlSearchAndReplaceTransform(XNode node, Regex regex, stri { foreach (var match in matchCollection.Cast()) { - if ((callback != null) && !callback(paragraph, match)) continue; + if ((callback != null) && !callback(paragraph, match)) + continue; - var runCollection = alignedRuns - .Skip(match.Index) - .Take(match.Length) - .ToList(); + var runCollection = alignedRuns.Skip(match.Index).Take(match.Length).ToList(); // uses the Skip / Take special semantics of array to implement efficient finding of sub array @@ -485,9 +597,7 @@ private static object PmlSearchAndReplaceTransform(XNode node, Regex regex, stri // in LINQ to XML that uses snapshot semantics and removes every element from // its parent. - var newFirstRun = new XElement(A.r, - firstRun.Element(A.rPr), - new XElement(A.t, replacement)); + var newFirstRun = new XElement(A.r, firstRun.Element(A.rPr), new XElement(A.t, replacement)); // creates a new run with proper run properties @@ -500,31 +610,30 @@ private static object PmlSearchAndReplaceTransform(XNode node, Regex regex, stri } var paragraphWithReplacedRuns = paragraphWithSplitRuns; - var groupedAdjacentRunsWithIdenticalFormatting = - paragraphWithReplacedRuns - .Elements() - .GroupAdjacent(ce => - { - if (ce.Name != A.r) - return DontConsolidate; - if ((ce.Elements().Count(e => e.Name != A.rPr) != 1) || (ce.Element(A.t) == null)) - return DontConsolidate; - - var rPr = ce.Element(A.rPr); - return rPr == null ? "" : rPr.ToString(SaveOptions.None); - }); - var paragraphWithConsolidatedRuns = new XElement(A.p, + var groupedAdjacentRunsWithIdenticalFormatting = paragraphWithReplacedRuns + .Elements() + .GroupAdjacent(ce => + { + if (ce.Name != A.r) + return DontConsolidate; + if ((ce.Elements().Count(e => e.Name != A.rPr) != 1) || (ce.Element(A.t) == null)) + return DontConsolidate; + + var rPr = ce.Element(A.rPr); + return rPr == null ? "" : rPr.ToString(SaveOptions.None); + }); + var paragraphWithConsolidatedRuns = new XElement( + A.p, groupedAdjacentRunsWithIdenticalFormatting.Select(g => { if (g.Key == DontConsolidate) - return (object) g; + return (object)g; var textValue = g.Select(r => r.Element(A.t).Value).StringConcatenate(); var xs = XmlUtil.GetXmlSpaceAttribute(textValue); - return new XElement(A.r, - g.First().Elements(A.rPr), - new XElement(A.t, xs, textValue)); - })); + return new XElement(A.r, g.First().Elements(A.rPr), new XElement(A.t, xs, textValue)); + }) + ); paragraph = paragraphWithConsolidatedRuns; } @@ -533,28 +642,31 @@ private static object PmlSearchAndReplaceTransform(XNode node, Regex regex, stri if ((element.Name == A.r) && element.Elements(A.t).Any()) { - return element.Elements() + return element + .Elements() .Where(e => e.Name != A.rPr) .Select(e => { if (e.Name == A.t) { - var s = (string) e; - var collectionOfSubRuns = s.Select(c => new XElement(A.r, + var s = (string)e; + var collectionOfSubRuns = s.Select(c => new XElement( + A.r, element.Elements(A.rPr), - new XElement(A.t, XmlUtil.GetXmlSpaceAttribute(c), c))); - return (object) collectionOfSubRuns; + new XElement(A.t, XmlUtil.GetXmlSpaceAttribute(c), c) + )); + return (object)collectionOfSubRuns; } - return new XElement(A.r, - element.Elements(A.rPr), - e); + return new XElement(A.r, element.Elements(A.rPr), e); }); } - return new XElement(element.Name, + return new XElement( + element.Name, element.Attributes(), - element.Nodes().Select(n => PmlSearchAndReplaceTransform(n, regex, replacement, callback, counter))); + element.Nodes().Select(n => PmlSearchAndReplaceTransform(n, regex, replacement, callback, counter)) + ); } private class ReplaceInternalInfo diff --git a/Clippit/OxPtHelpers.cs b/Clippit/OxPtHelpers.cs index dbadecc7..053a5493 100644 --- a/Clippit/OxPtHelpers.cs +++ b/Clippit/OxPtHelpers.cs @@ -5,17 +5,17 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Xml; using System.Xml.Linq; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Wordprocessing; -using DocumentFormat.OpenXml.Validation; -using System.Text; using Clippit.Excel; using Clippit.Internal; using Clippit.PowerPoint; using Clippit.Word; using DocumentFormat.OpenXml; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Validation; +using DocumentFormat.OpenXml.Wordprocessing; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Formats.Gif; @@ -34,7 +34,8 @@ public static WmlDocument AppendParagraphToDocument( bool isUnderline, string foreColor, string backColor, - string styleName) + string styleName + ) { using var streamDoc = new OpenXmlMemoryStreamDocument(wmlDoc); using (var wDoc = streamDoc.GetWordprocessingDocument()) @@ -55,13 +56,13 @@ public static WmlDocument AppendParagraphToDocument( if (isItalic) runProperties.AppendChild(new Italic()); - if (!string.IsNullOrEmpty(foreColor)) { var colorValue = ColorParser.FromName(foreColor).ToArgb(); if (colorValue == 0) throw new OpenXmlPowerToolsException( - $"Add-DocxText: The specified color {foreColor} is unsupported, Please specify the valid color. Ex, Red, Green"); + $"Add-DocxText: The specified color {foreColor} is unsupported, Please specify the valid color. Ex, Red, Green" + ); var ColorHex = $"{colorValue:x6}"; runProperties.AppendChild(new Color() { Val = ColorHex.Substring(2) }); @@ -75,10 +76,13 @@ public static WmlDocument AppendParagraphToDocument( var colorShade = ColorParser.FromName(backColor).ToArgb(); if (colorShade == 0) throw new OpenXmlPowerToolsException( - $"Add-DocxText: The specified color {foreColor} is unsupported, Please specify the valid color. Ex, Red, Green"); + $"Add-DocxText: The specified color {foreColor} is unsupported, Please specify the valid color. Ex, Red, Green" + ); var ColorShadeHex = $"{colorShade:x6}"; - runProperties.AppendChild(new Shading() { Fill = ColorShadeHex.Substring(2), Val = ShadingPatternValues.Clear }); + runProperties.AppendChild( + new Shading() { Fill = ColorShadeHex.Substring(2), Val = ShadingPatternValues.Clear } + ); } if (!string.IsNullOrEmpty(styleName)) @@ -312,12 +316,16 @@ public static WmlDocument AppendParagraphToDocument( using var defaultDotx = WordprocessingDocument.Open(memoryStream, true); //Get the specified style from Default.dotx template for paragraph - var templateStyle = defaultDotx.MainDocumentPart.StyleDefinitionsPart.Styles.Elements