Skip to content

Commit edbe502

Browse files
committed
Fix Multiple tags format error #37
1 parent a4cf1f2 commit edbe502

File tree

4 files changed

+98
-52
lines changed

4 files changed

+98
-52
lines changed

samples/docx/TestIssue17.docx

118 Bytes
Binary file not shown.

samples/docx/TestIssue37.docx

12 KB
Binary file not shown.

src/MiniWord/MiniWord.Implment.cs

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -41,59 +41,9 @@ private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Diction
4141
}
4242
private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
4343
{
44+
// avoid {{tag}} like <t>{</t><t>{</t>
45+
AvoidSplitTagText(xmlElement);
4446

45-
// Avoid not standard string format e.g. {{<t>tag</t>}}
46-
//foreach (var tag in tags)
47-
//{
48-
// var regexStr = string.Concat(@"((\{\{(?:(?!\{\{|}}).)*>)|\{\{)", tag.Key, @"(}}|<.*?}})");
49-
50-
// xmlElement.InnerXml = Regex.Replace(xmlElement.InnerXml, regexStr, $"{{{{{tag.Key?.ToString()}}}}}", RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant);
51-
//}
52-
// Avoid not standard string format e.g. {{<t>tag</t>}}
53-
{
54-
var paragraphs = xmlElement.Descendants<Paragraph>().ToArray();
55-
foreach (var p in paragraphs)
56-
{
57-
var runs = p.Descendants<Run>().ToArray();
58-
var isMatch = tags.Any(tag =>
59-
{
60-
var b = p.InnerText.Contains($"{{{{{tag.Key}}}}}");
61-
if (!b && tag.Value is IEnumerable)
62-
{
63-
foreach (var item in tag.Value as IEnumerable)
64-
{
65-
if (item is Dictionary<string, object>)
66-
{
67-
foreach (var dic in item as Dictionary<string, object>)
68-
{
69-
b = p.InnerText.Contains($"{{{{{tag.Key}.{dic.Key}}}}}");
70-
if (b)
71-
break;
72-
}
73-
}
74-
break;
75-
}
76-
}
77-
return b;
78-
});
79-
if (isMatch)
80-
{
81-
var newText = p.InnerText?.ToString();
82-
foreach (var run in runs.Skip(1))
83-
run.RemoveAllChildren<Text>();
84-
if (runs.Length > 0)
85-
{
86-
var texts = runs[0].Descendants<Text>().ToArray();
87-
if (texts.Length > 0)
88-
{
89-
foreach (var text in texts.Skip(1))
90-
text.RemoveAllChildren();
91-
texts[0].Text = newText;
92-
}
93-
}
94-
}
95-
}
96-
}
9747
//Tables
9848
var tables = xmlElement.Descendants<Table>().ToArray();
9949
{
@@ -143,6 +93,57 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum
14393
ReplaceText(xmlElement, docx, tags);
14494
}
14595

96+
private static void AvoidSplitTagText(OpenXmlElement xmlElement)
97+
{
98+
var texts = xmlElement.Descendants<Text>().ToList();
99+
var pool = new List<Text>();
100+
var sb = new StringBuilder();
101+
var needAppend = false;
102+
foreach (var text in texts)
103+
{
104+
var clear = false;
105+
if (text.InnerText.StartsWith("{"))
106+
{
107+
needAppend = true;
108+
}
109+
if (needAppend)
110+
{
111+
sb.Append(text.InnerText);
112+
pool.Add(text);
113+
114+
var s = sb.ToString(); //TODO:
115+
// TODO: check tag exist
116+
// TODO: record tag text if without tag then system need to clear them
117+
// TODO: every {{tag}} one <t>for them</t> and add text before first text and copy first one and remove {{, tagname, }}
118+
119+
if (!s.StartsWith("{{"))
120+
clear = true;
121+
else if (s.Contains("{{") && s.Contains("}}"))
122+
{
123+
if (sb.Length <= 1000) // avoid too big tag
124+
{
125+
var first = pool.First();
126+
var newText = first.Clone() as Text;
127+
newText.Text = s;
128+
first.Parent.InsertBefore(newText, first);
129+
foreach (var t in pool)
130+
{
131+
t.Text = "";
132+
}
133+
}
134+
clear = true;
135+
}
136+
}
137+
138+
if (clear)
139+
{
140+
sb.Clear();
141+
pool.Clear();
142+
needAppend = false;
143+
}
144+
}
145+
}
146+
146147
private static void ReplaceText(OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
147148
{
148149
var paragraphs = xmlElement.Descendants<Paragraph>().ToArray();

tests/MiniWordTests/IssueTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,51 @@ namespace MiniWordTests
99
{
1010
public class IssueTests
1111
{
12+
13+
/// <summary>
14+
/// [Text color multiple tags format error · Issue #37 · mini-software/MiniWord]
15+
/// (https://github.com/mini-software/MiniWord/issues/37)
16+
/// </summary>
17+
[Fact]
18+
public void TestIssue37()
19+
{
20+
{
21+
var path = PathHelper.GetTempFilePath();
22+
var templatePath = PathHelper.GetFile("TestIssue37.docx");
23+
var value = new Dictionary<string, object>
24+
{
25+
["Content"] = "Test",
26+
["Content2"] = "Test2",
27+
};
28+
MiniWord.SaveAsByTemplate(path, templatePath, value);
29+
var xml = Helpers.GetZipFileContent(path, "word/document.xml");
30+
Assert.Contains(@"Test", xml);
31+
Assert.Contains(@"Test2", xml);
32+
}
33+
34+
{
35+
var path = PathHelper.GetTempFilePath();
36+
var templatePath = PathHelper.GetFile("TestIssue37.docx");
37+
var value = new Dictionary<string, object>
38+
{
39+
["Content"] = new MiniWordHyperLink()
40+
{
41+
Url = "https://google.com",
42+
Text = "Test1!!"
43+
},
44+
["Content2"] = new MiniWordHyperLink()
45+
{
46+
Url = "https://google.com",
47+
Text = "Test2!!"
48+
},
49+
};
50+
MiniWord.SaveAsByTemplate(path, templatePath, value);
51+
var xml = Helpers.GetZipFileContent(path, "word/document.xml");
52+
Assert.Contains(@"Test", xml);
53+
Assert.Contains(@"Test2", xml);
54+
}
55+
}
56+
1257
[Fact]
1358
public void TestDemo04()
1459
{

0 commit comments

Comments
 (0)