dimcode-darwin-x64 0.1.2-beta.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/bin/dimcode +0 -0
  2. package/package.json +1 -1
  3. package/bin/runtime/sandbox/dim-sandbox-runner +0 -0
  4. package/bin/runtime/sandbox/manifest.json +0 -15
  5. package/bin/skills-assets/deep-investigate/SKILL.md +0 -101
  6. package/bin/skills-assets/deep-investigate/references/prompts.md +0 -75
  7. package/bin/skills-assets/deep-investigate/references/templates.md +0 -73
  8. package/bin/skills-assets/deep-investigate/references/thinking-tools.md +0 -36
  9. package/bin/skills-assets/docs-sprint/SKILL.md +0 -73
  10. package/bin/skills-assets/docs-sprint/agents/openai.yaml +0 -4
  11. package/bin/skills-assets/docs-sprint/references/contract-discipline.md +0 -30
  12. package/bin/skills-assets/docs-sprint/references/delivery-plan.md +0 -162
  13. package/bin/skills-assets/docs-sprint/references/documentation-system.md +0 -109
  14. package/bin/skills-assets/docs-sprint/references/ui-layout.md +0 -73
  15. package/bin/skills-assets/docs-sprint/references/worktree-guide.md +0 -45
  16. package/bin/skills-assets/docx/SKILL.md +0 -273
  17. package/bin/skills-assets/docx/assets/styles/academic_styles.xml +0 -250
  18. package/bin/skills-assets/docx/assets/styles/corporate_styles.xml +0 -284
  19. package/bin/skills-assets/docx/assets/styles/default_styles.xml +0 -449
  20. package/bin/skills-assets/docx/assets/xsd/aesthetic-rules.xsd +0 -470
  21. package/bin/skills-assets/docx/assets/xsd/business-rules.xsd +0 -130
  22. package/bin/skills-assets/docx/assets/xsd/common-types.xsd +0 -159
  23. package/bin/skills-assets/docx/assets/xsd/wml-subset.xsd +0 -589
  24. package/bin/skills-assets/docx/references/cjk_typography.md +0 -357
  25. package/bin/skills-assets/docx/references/cjk_university_template_guide.md +0 -184
  26. package/bin/skills-assets/docx/references/comments_guide.md +0 -191
  27. package/bin/skills-assets/docx/references/design_good_bad_examples.md +0 -829
  28. package/bin/skills-assets/docx/references/design_principles.md +0 -819
  29. package/bin/skills-assets/docx/references/openxml_element_order.md +0 -308
  30. package/bin/skills-assets/docx/references/openxml_encyclopedia_part1.md +0 -4061
  31. package/bin/skills-assets/docx/references/openxml_encyclopedia_part2.md +0 -2820
  32. package/bin/skills-assets/docx/references/openxml_encyclopedia_part3.md +0 -3381
  33. package/bin/skills-assets/docx/references/openxml_namespaces.md +0 -82
  34. package/bin/skills-assets/docx/references/openxml_units.md +0 -72
  35. package/bin/skills-assets/docx/references/scenario_a_create.md +0 -284
  36. package/bin/skills-assets/docx/references/scenario_b_edit_content.md +0 -295
  37. package/bin/skills-assets/docx/references/scenario_c_apply_template.md +0 -456
  38. package/bin/skills-assets/docx/references/track_changes_guide.md +0 -200
  39. package/bin/skills-assets/docx/references/troubleshooting.md +0 -506
  40. package/bin/skills-assets/docx/references/typography_guide.md +0 -294
  41. package/bin/skills-assets/docx/references/xsd_validation_guide.md +0 -158
  42. package/bin/skills-assets/docx/scripts/doc_to_docx.sh +0 -40
  43. package/bin/skills-assets/docx/scripts/docx_preview.sh +0 -37
  44. package/bin/skills-assets/docx/scripts/dotnet/Docx.Cli/Docx.Cli.csproj +0 -19
  45. package/bin/skills-assets/docx/scripts/dotnet/Docx.Cli/Program.cs +0 -18
  46. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/AnalyzeCommand.cs +0 -147
  47. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/ApplyTemplateCommand.cs +0 -322
  48. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/CreateCommand.cs +0 -324
  49. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/DiffCommand.cs +0 -155
  50. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/EditContentCommand.cs +0 -487
  51. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/FixOrderCommand.cs +0 -108
  52. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/MergeRunsCommand.cs +0 -122
  53. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Commands/ValidateCommand.cs +0 -107
  54. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Docx.Core.csproj +0 -15
  55. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/CommentSynchronizer.cs +0 -169
  56. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/ElementOrder.cs +0 -80
  57. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/NamespaceConstants.cs +0 -42
  58. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/RunMerger.cs +0 -81
  59. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/StyleAnalyzer.cs +0 -81
  60. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/TrackChangesHelper.cs +0 -99
  61. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/OpenXml/UnitConverter.cs +0 -23
  62. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/AestheticRecipeSamples.cs +0 -1832
  63. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/AestheticRecipeSamples_Batch1.cs +0 -910
  64. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/AestheticRecipeSamples_Batch2.cs +0 -999
  65. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/AestheticRecipeSamples_Batch3.cs +0 -1048
  66. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/AestheticRecipeSamples_Batch4.cs +0 -1038
  67. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/CharacterFormattingSamples.cs +0 -1020
  68. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/DocumentCreationSamples.cs +0 -1121
  69. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/FieldAndTocSamples.cs +0 -624
  70. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/FootnoteAndCommentSamples.cs +0 -675
  71. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/HeaderFooterSamples.cs +0 -838
  72. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/ImageSamples.cs +0 -917
  73. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/ListAndNumberingSamples.cs +0 -826
  74. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/ParagraphFormattingSamples.cs +0 -1199
  75. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/StyleSystemSamples.cs +0 -1487
  76. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/TableSamples.cs +0 -1163
  77. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Samples/TrackChangesSamples.cs +0 -595
  78. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Typography/CjkHelper.cs +0 -39
  79. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Typography/FontDefaults.cs +0 -24
  80. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Typography/PageSizes.cs +0 -20
  81. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Validation/BusinessRuleValidator.cs +0 -224
  82. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Validation/GateCheckValidator.cs +0 -148
  83. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Validation/ValidationResult.cs +0 -23
  84. package/bin/skills-assets/docx/scripts/dotnet/Docx.Core/Validation/XsdValidator.cs +0 -69
  85. package/bin/skills-assets/docx/scripts/dotnet/Docx.slnx +0 -4
  86. package/bin/skills-assets/docx/scripts/env_check.sh +0 -196
  87. package/bin/skills-assets/docx/scripts/setup.ps1 +0 -274
  88. package/bin/skills-assets/docx/scripts/setup.sh +0 -504
  89. package/bin/skills-assets/pdf/README.md +0 -222
  90. package/bin/skills-assets/pdf/SKILL.md +0 -191
  91. package/bin/skills-assets/pdf/design/design.md +0 -381
  92. package/bin/skills-assets/pdf/scripts/cover.py +0 -1579
  93. package/bin/skills-assets/pdf/scripts/fill_inspect.py +0 -200
  94. package/bin/skills-assets/pdf/scripts/fill_write.py +0 -242
  95. package/bin/skills-assets/pdf/scripts/make.sh +0 -491
  96. package/bin/skills-assets/pdf/scripts/merge.py +0 -112
  97. package/bin/skills-assets/pdf/scripts/palette.py +0 -521
  98. package/bin/skills-assets/pdf/scripts/reformat_parse.py +0 -374
  99. package/bin/skills-assets/pdf/scripts/render_body.py +0 -1052
  100. package/bin/skills-assets/pdf/scripts/render_cover.js +0 -111
  101. package/bin/skills-assets/pptx-generator/SKILL.md +0 -248
  102. package/bin/skills-assets/pptx-generator/references/design-system.md +0 -392
  103. package/bin/skills-assets/pptx-generator/references/editing.md +0 -162
  104. package/bin/skills-assets/pptx-generator/references/pitfalls.md +0 -112
  105. package/bin/skills-assets/pptx-generator/references/pptxgenjs.md +0 -420
  106. package/bin/skills-assets/pptx-generator/references/slide-types.md +0 -413
  107. package/bin/skills-assets/skill-creator/SKILL.md +0 -368
  108. package/bin/skills-assets/skill-creator/agents/openai.yaml +0 -5
  109. package/bin/skills-assets/skill-creator/assets/skill-creator-small.svg +0 -3
  110. package/bin/skills-assets/skill-creator/assets/skill-creator.png +0 -0
  111. package/bin/skills-assets/skill-creator/license.txt +0 -202
  112. package/bin/skills-assets/skill-creator/references/openai_yaml.md +0 -49
  113. package/bin/skills-assets/skill-creator/scripts/generate_openai_yaml.py +0 -226
  114. package/bin/skills-assets/skill-creator/scripts/init_skill.py +0 -397
  115. package/bin/skills-assets/skill-creator/scripts/quick_validate.py +0 -101
  116. package/bin/skills-assets/skill-installer/LICENSE.txt +0 -202
  117. package/bin/skills-assets/skill-installer/SKILL.md +0 -58
  118. package/bin/skills-assets/skill-installer/agents/openai.yaml +0 -5
  119. package/bin/skills-assets/skill-installer/assets/skill-installer-small.svg +0 -3
  120. package/bin/skills-assets/skill-installer/assets/skill-installer.png +0 -0
  121. package/bin/skills-assets/skill-installer/scripts/github_utils.py +0 -21
  122. package/bin/skills-assets/skill-installer/scripts/install-skill-from-github.py +0 -308
  123. package/bin/skills-assets/skill-installer/scripts/list-skills.py +0 -107
  124. package/bin/skills-assets/xlsx/SKILL.md +0 -137
  125. package/bin/skills-assets/xlsx/references/create.md +0 -691
  126. package/bin/skills-assets/xlsx/references/edit.md +0 -684
  127. package/bin/skills-assets/xlsx/references/fix.md +0 -37
  128. package/bin/skills-assets/xlsx/references/format.md +0 -768
  129. package/bin/skills-assets/xlsx/references/ooxml-cheatsheet.md +0 -231
  130. package/bin/skills-assets/xlsx/references/read-analyze.md +0 -97
  131. package/bin/skills-assets/xlsx/references/validate.md +0 -772
  132. package/bin/skills-assets/xlsx/scripts/formula_check.py +0 -422
  133. package/bin/skills-assets/xlsx/scripts/libreoffice_recalc.py +0 -248
  134. package/bin/skills-assets/xlsx/scripts/shared_strings_builder.py +0 -163
  135. package/bin/skills-assets/xlsx/scripts/style_audit.py +0 -575
  136. package/bin/skills-assets/xlsx/scripts/xlsx_add_column.py +0 -395
  137. package/bin/skills-assets/xlsx/scripts/xlsx_insert_row.py +0 -274
  138. package/bin/skills-assets/xlsx/scripts/xlsx_pack.py +0 -87
  139. package/bin/skills-assets/xlsx/scripts/xlsx_reader.py +0 -362
  140. package/bin/skills-assets/xlsx/scripts/xlsx_shift_rows.py +0 -396
  141. package/bin/skills-assets/xlsx/scripts/xlsx_unpack.py +0 -130
  142. package/bin/skills-assets/xlsx/templates/minimal_xlsx/[Content_Types].xml +0 -9
  143. package/bin/skills-assets/xlsx/templates/minimal_xlsx/_rels/.rels +0 -6
  144. package/bin/skills-assets/xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +0 -19
  145. package/bin/skills-assets/xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +0 -33
  146. package/bin/skills-assets/xlsx/templates/minimal_xlsx/xl/styles.xml +0 -160
  147. package/bin/skills-assets/xlsx/templates/minimal_xlsx/xl/workbook.xml +0 -30
  148. package/bin/skills-assets/xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +0 -70
@@ -1,122 +0,0 @@
1
- using System.CommandLine;
2
- using System.IO.Compression;
3
- using System.Xml.Linq;
4
-
5
- namespace Docx.Core.Commands;
6
-
7
- public static class MergeRunsCommand
8
- {
9
- private static readonly XNamespace W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
10
-
11
- public static Command Create()
12
- {
13
- var inputOption = new Option<string>("--input") { Description = "DOCX file to optimize", Required = true };
14
- var outputOption = new Option<string>("--output") { Description = "Output path (default: overwrite input)" };
15
- var dryRunOption = new Option<bool>("--dry-run") { Description = "Report without modifying" };
16
-
17
- var cmd = new Command("merge-runs", "Merge adjacent runs with identical formatting")
18
- {
19
- inputOption, outputOption, dryRunOption
20
- };
21
-
22
- cmd.SetAction((parseResult) =>
23
- {
24
- var input = parseResult.GetValue(inputOption)!;
25
- var output = parseResult.GetValue(outputOption) ?? input;
26
- var dryRun = parseResult.GetValue(dryRunOption);
27
-
28
- if (!File.Exists(input))
29
- {
30
- Console.Error.WriteLine($"File not found: {input}");
31
- return;
32
- }
33
-
34
- var tempPath = Path.GetTempFileName();
35
- File.Copy(input, tempPath, true);
36
-
37
- using var zip = ZipFile.Open(tempPath, ZipArchiveMode.Update);
38
- var entry = zip.GetEntry("word/document.xml");
39
- if (entry == null)
40
- {
41
- Console.Error.WriteLine("Not a valid DOCX: missing word/document.xml");
42
- return;
43
- }
44
-
45
- XDocument doc;
46
- using (var stream = entry.Open())
47
- doc = XDocument.Load(stream);
48
-
49
- int originalCount = 0;
50
- int mergedCount = 0;
51
-
52
- foreach (var p in doc.Descendants(W + "p"))
53
- {
54
- var runs = p.Elements(W + "r").ToList();
55
- originalCount += runs.Count;
56
-
57
- for (int i = runs.Count - 1; i > 0; i--)
58
- {
59
- var current = runs[i];
60
- var previous = runs[i - 1];
61
-
62
- var curProps = current.Element(W + "rPr")?.ToString() ?? "";
63
- var prevProps = previous.Element(W + "rPr")?.ToString() ?? "";
64
-
65
- if (curProps == prevProps)
66
- {
67
- // Only merge if both contain only text elements
68
- var curChildren = current.Elements().Where(e => e.Name != W + "rPr").ToList();
69
- var prevChildren = previous.Elements().Where(e => e.Name != W + "rPr").ToList();
70
-
71
- if (curChildren.All(e => e.Name == W + "t") && prevChildren.All(e => e.Name == W + "t"))
72
- {
73
- var prevText = previous.Elements(W + "t").LastOrDefault();
74
- var curText = current.Elements(W + "t").FirstOrDefault();
75
-
76
- if (prevText != null && curText != null)
77
- {
78
- prevText.Value += curText.Value;
79
- prevText.SetAttributeValue(XNamespace.Xml + "space", "preserve");
80
-
81
- foreach (var extra in current.Elements(W + "t").Skip(1))
82
- {
83
- previous.Add(new XElement(extra));
84
- }
85
-
86
- current.Remove();
87
- runs.RemoveAt(i);
88
- }
89
- }
90
- }
91
- }
92
-
93
- mergedCount += runs.Count;
94
- }
95
-
96
- if (dryRun)
97
- {
98
- Console.WriteLine($"Original runs: {originalCount}");
99
- Console.WriteLine($"After merge: {mergedCount}");
100
- Console.WriteLine($"Reduction: {(originalCount > 0 ? (originalCount - mergedCount) * 100.0 / originalCount : 0):F1}%");
101
- File.Delete(tempPath);
102
- return;
103
- }
104
-
105
- entry.Delete();
106
- var newEntry = zip.CreateEntry("word/document.xml", CompressionLevel.Optimal);
107
- using (var stream = newEntry.Open())
108
- doc.Save(stream);
109
-
110
- zip.Dispose();
111
- File.Copy(tempPath, output, true);
112
- File.Delete(tempPath);
113
-
114
- Console.WriteLine($"Original runs: {originalCount}");
115
- Console.WriteLine($"After merge: {mergedCount}");
116
- Console.WriteLine($"Reduction: {(originalCount > 0 ? (originalCount - mergedCount) * 100.0 / originalCount : 0):F1}%");
117
- Console.WriteLine($"Written to: {output}");
118
- });
119
-
120
- return cmd;
121
- }
122
- }
@@ -1,107 +0,0 @@
1
- using System.CommandLine;
2
- using System.Text.Json;
3
- using Docx.Core.Validation;
4
-
5
- namespace Docx.Core.Commands;
6
-
7
- public static class ValidateCommand
8
- {
9
- public static Command Create()
10
- {
11
- var inputOption = new Option<string>("--input") { Description = "DOCX file to validate", Required = true };
12
- var xsdOption = new Option<string>("--xsd") { Description = "XSD schema path for XML validation" };
13
- var businessOption = new Option<bool>("--business") { Description = "Run business rule validation" };
14
- var gateCheckOption = new Option<string>("--gate-check") { Description = "Template DOCX for gate-check validation" };
15
- var jsonOption = new Option<bool>("--json") { Description = "Output results as JSON" };
16
-
17
- var cmd = new Command("validate", "Validate DOCX structure and content")
18
- {
19
- inputOption, xsdOption, businessOption, gateCheckOption, jsonOption
20
- };
21
-
22
- cmd.SetAction((parseResult) =>
23
- {
24
- var input = parseResult.GetValue(inputOption)!;
25
- var xsd = parseResult.GetValue(xsdOption);
26
- var business = parseResult.GetValue(businessOption);
27
- var gateCheck = parseResult.GetValue(gateCheckOption);
28
- var asJson = parseResult.GetValue(jsonOption);
29
-
30
- if (!File.Exists(input))
31
- {
32
- Console.Error.WriteLine($"File not found: {input}");
33
- return;
34
- }
35
-
36
- var combinedResult = new ValidationResult();
37
- GateCheckResult? gateResult = null;
38
-
39
- if (xsd != null)
40
- {
41
- var xsdValidator = new XsdValidator();
42
- combinedResult.Merge(xsdValidator.Validate(input, xsd));
43
- }
44
-
45
- if (business)
46
- {
47
- var bizValidator = new BusinessRuleValidator();
48
- combinedResult.Merge(bizValidator.Validate(input));
49
- }
50
-
51
- if (gateCheck != null)
52
- {
53
- var gateValidator = new GateCheckValidator();
54
- gateResult = gateValidator.Validate(input, gateCheck);
55
- }
56
-
57
- if (asJson)
58
- {
59
- var output = new
60
- {
61
- isValid = combinedResult.IsValid && (gateResult?.Passed ?? true),
62
- errors = combinedResult.Errors,
63
- warnings = combinedResult.Warnings,
64
- gateCheck = gateResult == null ? null : new
65
- {
66
- passed = gateResult.Passed,
67
- violations = gateResult.Violations
68
- }
69
- };
70
- Console.WriteLine(JsonSerializer.Serialize(output, new JsonSerializerOptions { WriteIndented = true }));
71
- }
72
- else
73
- {
74
- if (combinedResult.Errors.Count > 0)
75
- {
76
- Console.WriteLine($"ERRORS ({combinedResult.Errors.Count}):");
77
- foreach (var e in combinedResult.Errors)
78
- Console.WriteLine($" [{e.Severity}] {e.Message}" + (e.LineNumber > 0 ? $" (line {e.LineNumber}:{e.LinePosition})" : ""));
79
- }
80
-
81
- if (combinedResult.Warnings.Count > 0)
82
- {
83
- Console.WriteLine($"WARNINGS ({combinedResult.Warnings.Count}):");
84
- foreach (var w in combinedResult.Warnings)
85
- Console.WriteLine($" [{w.Severity}] {w.Message}");
86
- }
87
-
88
- if (gateResult != null)
89
- {
90
- Console.WriteLine(gateResult.Passed ? "GATE CHECK: PASSED" : "GATE CHECK: FAILED");
91
- foreach (var v in gateResult.Violations)
92
- Console.WriteLine($" - {v}");
93
- }
94
-
95
- if (combinedResult.IsValid && (gateResult?.Passed ?? true))
96
- Console.WriteLine("Validation: PASSED");
97
- else
98
- Console.WriteLine("Validation: FAILED");
99
- }
100
-
101
- if (!combinedResult.IsValid || gateResult is { Passed: false })
102
- Environment.ExitCode = 1;
103
- });
104
-
105
- return cmd;
106
- }
107
- }
@@ -1,15 +0,0 @@
1
- <Project Sdk="Microsoft.NET.Sdk">
2
-
3
- <PropertyGroup>
4
- <TargetFramework>net8.0</TargetFramework>
5
- <ImplicitUsings>enable</ImplicitUsings>
6
- <Nullable>enable</Nullable>
7
- <NeutralLanguage>en</NeutralLanguage>
8
- </PropertyGroup>
9
-
10
- <ItemGroup>
11
- <PackageReference Include="DocumentFormat.OpenXml" Version="3.5.1" />
12
- <PackageReference Include="System.CommandLine" Version="2.0.5" />
13
- </ItemGroup>
14
-
15
- </Project>
@@ -1,169 +0,0 @@
1
- using DocumentFormat.OpenXml;
2
- using DocumentFormat.OpenXml.Packaging;
3
- using DocumentFormat.OpenXml.Wordprocessing;
4
-
5
- namespace Docx.Core.OpenXml;
6
-
7
- /// <summary>
8
- /// Manages the 4-file comment system (comments.xml, commentsExtended.xml,
9
- /// commentsIds.xml, commentsExtensible.xml) plus document.xml markers.
10
- /// </summary>
11
- public static class CommentSynchronizer
12
- {
13
- /// <summary>
14
- /// Adds a comment to the document, updating all required parts.
15
- /// </summary>
16
- public static int AddComment(WordprocessingDocument doc, string text, string author, string rangeBookmark)
17
- {
18
- var mainPart = doc.MainDocumentPart
19
- ?? throw new InvalidOperationException("Document has no main part.");
20
-
21
- int commentId = GetNextCommentId(doc);
22
-
23
- // Ensure comments part exists
24
- var commentsPart = mainPart.WordprocessingCommentsPart
25
- ?? mainPart.AddNewPart<WordprocessingCommentsPart>();
26
-
27
- if (commentsPart.Comments == null)
28
- commentsPart.Comments = new Comments();
29
-
30
- // Create the comment
31
- var comment = new Comment
32
- {
33
- Id = commentId.ToString(),
34
- Author = author,
35
- Date = DateTime.UtcNow,
36
- Initials = author.Length > 0 ? author[..1].ToUpperInvariant() : "A"
37
- };
38
- comment.Append(new Paragraph(new Run(new Text(text))));
39
- commentsPart.Comments.Append(comment);
40
-
41
- // Add range markers in document body
42
- var body = mainPart.Document.Body;
43
- if (body != null)
44
- {
45
- // Find bookmark or append at end
46
- var rangeStart = new CommentRangeStart { Id = commentId.ToString() };
47
- var rangeEnd = new CommentRangeEnd { Id = commentId.ToString() };
48
- var reference = new Run(new CommentReference { Id = commentId.ToString() });
49
-
50
- body.Append(rangeStart);
51
- body.Append(rangeEnd);
52
- body.Append(new Paragraph(reference));
53
- }
54
-
55
- return commentId;
56
- }
57
-
58
- /// <summary>
59
- /// Adds a reply to an existing comment.
60
- /// </summary>
61
- public static int AddReply(WordprocessingDocument doc, int parentCommentId, string text, string author)
62
- {
63
- var mainPart = doc.MainDocumentPart
64
- ?? throw new InvalidOperationException("Document has no main part.");
65
-
66
- var commentsPart = mainPart.WordprocessingCommentsPart
67
- ?? throw new InvalidOperationException("Document has no comments part.");
68
-
69
- int replyId = GetNextCommentId(doc);
70
-
71
- var reply = new Comment
72
- {
73
- Id = replyId.ToString(),
74
- Author = author,
75
- Date = DateTime.UtcNow,
76
- Initials = author.Length > 0 ? author[..1].ToUpperInvariant() : "A"
77
- };
78
- reply.Append(new Paragraph(new Run(new Text(text))));
79
- commentsPart.Comments?.Append(reply);
80
-
81
- // Link reply to parent via commentsExtended.xml
82
- LinkReplyToParent(doc, replyId, parentCommentId);
83
-
84
- return replyId;
85
- }
86
-
87
- /// <summary>
88
- /// Marks a comment as resolved/done by setting done="1" in commentsExtended.xml.
89
- /// Uses raw XML manipulation since these extended parts lack typed SDK support.
90
- /// </summary>
91
- public static void ResolveComment(WordprocessingDocument doc, int commentId)
92
- {
93
- var mainPart = doc.MainDocumentPart;
94
- if (mainPart == null) return;
95
-
96
- // commentsExtended.xml is an untyped part — manipulate via raw XML
97
- const string ceUri = "http://schemas.microsoft.com/office/word/2018/wordml/cex";
98
- foreach (var part in mainPart.Parts)
99
- {
100
- if (part.OpenXmlPart.ContentType.Contains("commentsExtensible"))
101
- {
102
- using var stream = part.OpenXmlPart.GetStream(FileMode.Open, FileAccess.ReadWrite);
103
- var xdoc = System.Xml.Linq.XDocument.Load(stream);
104
- var ns = System.Xml.Linq.XNamespace.Get(ceUri);
105
- var commentEl = xdoc.Descendants(ns + "comment")
106
- .FirstOrDefault(e => e.Attribute(ns + "paraId")?.Value != null);
107
- // Set done flag if element found for this comment
108
- if (commentEl != null)
109
- {
110
- commentEl.SetAttributeValue("done", "1");
111
- stream.SetLength(0);
112
- xdoc.Save(stream);
113
- }
114
- return;
115
- }
116
- }
117
- }
118
-
119
- /// <summary>
120
- /// Links a reply comment to its parent via commentsExtended.xml (w15:commentEx).
121
- /// Uses raw XML since the extended comment parts lack typed SDK support.
122
- /// </summary>
123
- private static void LinkReplyToParent(WordprocessingDocument doc, int replyId, int parentCommentId)
124
- {
125
- var mainPart = doc.MainDocumentPart;
126
- if (mainPart == null) return;
127
-
128
- const string w15Uri = "http://schemas.microsoft.com/office/word/2012/wordml";
129
- var w15 = System.Xml.Linq.XNamespace.Get(w15Uri);
130
-
131
- // Find or create commentsExtended part
132
- foreach (var part in mainPart.Parts)
133
- {
134
- if (part.OpenXmlPart.ContentType.Contains("commentsExtended"))
135
- {
136
- using var stream = part.OpenXmlPart.GetStream(FileMode.Open, FileAccess.ReadWrite);
137
- var xdoc = System.Xml.Linq.XDocument.Load(stream);
138
- var root = xdoc.Root;
139
- if (root == null) return;
140
-
141
- root.Add(new System.Xml.Linq.XElement(w15 + "commentEx",
142
- new System.Xml.Linq.XAttribute(w15 + "paraId", replyId.ToString("X8")),
143
- new System.Xml.Linq.XAttribute(w15 + "paraIdParent", parentCommentId.ToString("X8")),
144
- new System.Xml.Linq.XAttribute(w15 + "done", "0")));
145
-
146
- stream.SetLength(0);
147
- xdoc.Save(stream);
148
- return;
149
- }
150
- }
151
- }
152
-
153
- /// <summary>
154
- /// Finds the maximum existing comment ID and returns the next one.
155
- /// </summary>
156
- public static int GetNextCommentId(WordprocessingDocument doc)
157
- {
158
- var commentsPart = doc.MainDocumentPart?.WordprocessingCommentsPart;
159
- if (commentsPart?.Comments == null) return 1;
160
-
161
- int maxId = 0;
162
- foreach (var comment in commentsPart.Comments.Elements<Comment>())
163
- {
164
- if (comment.Id?.Value != null && int.TryParse(comment.Id.Value, out int id) && id > maxId)
165
- maxId = id;
166
- }
167
- return maxId + 1;
168
- }
169
- }
@@ -1,80 +0,0 @@
1
- using System.Xml.Linq;
2
-
3
- namespace Docx.Core.OpenXml;
4
-
5
- /// <summary>
6
- /// Defines canonical child element ordering for key OpenXML parent elements
7
- /// and provides reordering utilities.
8
- /// </summary>
9
- public static class ElementOrder
10
- {
11
- private static readonly Dictionary<string, string[]> OrderMap = new()
12
- {
13
- ["w:body"] = ["w:p", "w:tbl", "w:sdt", "w:sectPr"],
14
- ["w:p"] = ["w:pPr", "w:hyperlink", "w:r", "w:ins", "w:del", "w:bookmarkStart", "w:bookmarkEnd", "w:commentRangeStart", "w:commentRangeEnd", "w:fldSimple"],
15
- ["w:pPr"] = ["w:pStyle", "w:keepNext", "w:keepLines", "w:pageBreakBefore", "w:widowControl", "w:numPr", "w:pBdr", "w:shd", "w:tabs", "w:suppressAutoHyphens", "w:spacing", "w:ind", "w:jc", "w:rPr", "w:sectPr", "w:pPrChange"],
16
- ["w:r"] = ["w:rPr", "w:t", "w:br", "w:tab", "w:cr", "w:sym", "w:drawing", "w:delText", "w:fldChar", "w:instrText", "w:lastRenderedPageBreak", "w:noBreakHyphen", "w:softHyphen"],
17
- ["w:rPr"] = ["w:rStyle", "w:rFonts", "w:b", "w:bCs", "w:i", "w:iCs", "w:caps", "w:smallCaps", "w:strike", "w:dstrike", "w:vanish", "w:color", "w:sz", "w:szCs", "w:u", "w:shd", "w:highlight", "w:lang", "w:rPrChange"],
18
- ["w:tbl"] = ["w:tblPr", "w:tblGrid", "w:tr"],
19
- ["w:tblPr"] = ["w:tblStyle", "w:tblpPr", "w:tblOverlap", "w:tblW", "w:jc", "w:tblCellSpacing", "w:tblInd", "w:tblBorders", "w:shd", "w:tblLayout", "w:tblCellMar", "w:tblLook", "w:tblPrChange"],
20
- ["w:tr"] = ["w:trPr", "w:tc"],
21
- ["w:trPr"] = ["w:cnfStyle", "w:divId", "w:gridBefore", "w:gridAfter", "w:wBefore", "w:wAfter", "w:cantSplit", "w:trHeight", "w:tblHeader", "w:tblCellSpacing", "w:jc", "w:hidden", "w:ins", "w:del", "w:trPrChange"],
22
- ["w:tc"] = ["w:tcPr", "w:p", "w:tbl"],
23
- ["w:tcPr"] = ["w:cnfStyle", "w:tcW", "w:gridSpan", "w:hMerge", "w:vMerge", "w:tcBorders", "w:shd", "w:noWrap", "w:tcMar", "w:textDirection", "w:tcFitText", "w:vAlign", "w:hideMark", "w:headers", "w:cellIns", "w:cellDel", "w:cellMerge", "w:tcPrChange"],
24
- ["w:sectPr"] = ["w:headerReference", "w:footerReference", "w:type", "w:pgSz", "w:pgMar", "w:paperSrc", "w:pgBorders", "w:lnNumType", "w:pgNumType", "w:cols", "w:formProt", "w:vAlign", "w:noEndnote", "w:titlePg", "w:textDirection", "w:bidi", "w:rtlGutter", "w:docGrid"],
25
- ["w:hdr"] = ["w:p", "w:tbl", "w:sdt"],
26
- ["w:ftr"] = ["w:p", "w:tbl", "w:sdt"],
27
- };
28
-
29
- /// <summary>
30
- /// Returns the canonical child ordering for a given parent element name (e.g. "w:p").
31
- /// Returns null if no ordering is defined.
32
- /// </summary>
33
- public static string[]? GetChildOrder(string parentElement)
34
- {
35
- return OrderMap.TryGetValue(parentElement, out var order) ? order : null;
36
- }
37
-
38
- /// <summary>
39
- /// Reorders children of the given XElement according to the canonical ordering rules.
40
- /// Children not listed in the ordering are placed at the end in their original order.
41
- /// </summary>
42
- public static void ReorderChildren(XElement parent)
43
- {
44
- var qualifiedName = GetQualifiedName(parent);
45
- var order = GetChildOrder(qualifiedName);
46
- if (order == null) return;
47
-
48
- var children = parent.Elements().ToList();
49
- if (children.Count <= 1) return;
50
-
51
- var orderIndex = new Dictionary<string, int>();
52
- for (int i = 0; i < order.Length; i++)
53
- orderIndex[order[i]] = i;
54
-
55
- int unknownBase = order.Length;
56
- int unknownCounter = 0;
57
-
58
- var sorted = children
59
- .Select(c => (Element: c, QName: GetQualifiedName(c)))
60
- .OrderBy(x => orderIndex.TryGetValue(x.QName, out var idx) ? idx : unknownBase + unknownCounter++)
61
- .Select(x => x.Element)
62
- .ToList();
63
-
64
- parent.RemoveNodes();
65
- foreach (var child in sorted)
66
- parent.Add(child);
67
- }
68
-
69
- private static string GetQualifiedName(XElement element)
70
- {
71
- var ns = element.Name.Namespace;
72
- var local = element.Name.LocalName;
73
-
74
- if (ns == Ns.W) return $"w:{local}";
75
- if (ns == Ns.R) return $"r:{local}";
76
- if (ns == Ns.MC) return $"mc:{local}";
77
-
78
- return local;
79
- }
80
- }
@@ -1,42 +0,0 @@
1
- using System.Xml.Linq;
2
-
3
- namespace Docx.Core.OpenXml;
4
-
5
- /// <summary>
6
- /// All OpenXML namespace URIs and common content/relationship type constants.
7
- /// </summary>
8
- public static class Ns
9
- {
10
- public static readonly XNamespace W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
11
- public static readonly XNamespace R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
12
- public static readonly XNamespace WP = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
13
- public static readonly XNamespace A = "http://schemas.openxmlformats.org/drawingml/2006/main";
14
- public static readonly XNamespace MC = "http://schemas.openxmlformats.org/markup-compatibility/2006";
15
- public static readonly XNamespace PIC = "http://schemas.openxmlformats.org/drawingml/2006/picture";
16
- public static readonly XNamespace W14 = "http://schemas.microsoft.com/office/word/2010/wordml";
17
- public static readonly XNamespace W15 = "http://schemas.microsoft.com/office/word/2012/wordml";
18
- public static readonly XNamespace W16CID = "http://schemas.microsoft.com/office/word/2016/wordml/cid";
19
- public static readonly XNamespace W16CEX = "http://schemas.microsoft.com/office/word/2018/wordml/cex";
20
- public static readonly XNamespace WPC = "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas";
21
- public static readonly XNamespace WPS = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
22
-
23
- // Content types
24
- public const string MainDocumentContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml";
25
- public const string StylesContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml";
26
- public const string HeaderContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml";
27
- public const string FooterContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml";
28
- public const string CommentsContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml";
29
-
30
- // Relationship types
31
- public const string DocumentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
32
- public const string StylesRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
33
- public const string HeaderRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
34
- public const string FooterRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
35
- public const string CommentsRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
36
- public const string ImageRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
37
- public const string HyperlinkRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
38
- public const string NumberingRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
39
- public const string FontTableRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
40
- public const string ThemeRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
41
- public const string SettingsRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
42
- }
@@ -1,81 +0,0 @@
1
- using System.Xml.Linq;
2
-
3
- namespace Docx.Core.OpenXml;
4
-
5
- /// <summary>
6
- /// Result of a run merge operation.
7
- /// </summary>
8
- public record RunMergeResult(int OriginalRunCount, int MergedRunCount, int SizeReductionBytes);
9
-
10
- /// <summary>
11
- /// Merges adjacent w:r elements with identical w:rPr formatting to reduce document size.
12
- /// </summary>
13
- public static class RunMerger
14
- {
15
- /// <summary>
16
- /// Merges adjacent runs with identical formatting in all paragraphs of the document body.
17
- /// </summary>
18
- public static RunMergeResult MergeRuns(XDocument document)
19
- {
20
- var body = document.Root?.Element(Ns.W + "body");
21
- if (body == null) return new(0, 0, 0);
22
-
23
- int originalCount = 0;
24
- int removedCount = 0;
25
-
26
- foreach (var paragraph in body.Descendants(Ns.W + "p"))
27
- {
28
- var runs = paragraph.Elements(Ns.W + "r").ToList();
29
- originalCount += runs.Count;
30
-
31
- for (int i = runs.Count - 1; i > 0; i--)
32
- {
33
- var current = runs[i];
34
- var previous = runs[i - 1];
35
-
36
- if (!AreRunPropertiesEqual(previous, current)) continue;
37
-
38
- // Merge text content from current into previous
39
- var prevText = GetOrCreateTextElement(previous);
40
- var currText = current.Element(Ns.W + "t");
41
- if (currText != null && prevText != null)
42
- {
43
- prevText.Value += currText.Value;
44
- // Preserve xml:space="preserve" if either has it
45
- if (currText.Attribute(XNamespace.Xml + "space")?.Value == "preserve" ||
46
- prevText.Value.StartsWith(' ') || prevText.Value.EndsWith(' '))
47
- {
48
- prevText.SetAttributeValue(XNamespace.Xml + "space", "preserve");
49
- }
50
- }
51
-
52
- current.Remove();
53
- removedCount++;
54
- }
55
- }
56
-
57
- return new(originalCount, originalCount - removedCount, 0);
58
- }
59
-
60
- private static bool AreRunPropertiesEqual(XElement run1, XElement run2)
61
- {
62
- var rPr1 = run1.Element(Ns.W + "rPr");
63
- var rPr2 = run2.Element(Ns.W + "rPr");
64
-
65
- if (rPr1 == null && rPr2 == null) return true;
66
- if (rPr1 == null || rPr2 == null) return false;
67
-
68
- return XNode.DeepEquals(rPr1, rPr2);
69
- }
70
-
71
- private static XElement? GetOrCreateTextElement(XElement run)
72
- {
73
- var t = run.Element(Ns.W + "t");
74
- if (t == null)
75
- {
76
- t = new XElement(Ns.W + "t");
77
- run.Add(t);
78
- }
79
- return t;
80
- }
81
- }