Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Word Export LT-21942: Fix export failure #169

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 44 additions & 42 deletions Src/xWorks/LcmWordGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public void Append(IFragment frag)
if (elem.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().Any())
{
// then need to append image in such a way that the relID is maintained
this.DocBody.AppendChild(CloneImageRun(frag, elem));
this.DocBody.AppendChild(CloneImageElement(frag, elem));
// wordWriter.WordFragment.AppendPhotoToParagraph(frag, elem, wordWriter.ForceNewParagraph);
}

Expand All @@ -417,19 +417,25 @@ public void Append(IFragment frag)
/// <summary>
/// Append a table to the doc fragment.
/// </summary>
public void AppendTable(WP.Table table)
/// <param name="copyFromFrag">If the table contains pictures, then this is the fragment
/// where we copy the picture data from.</param>
/// <param name="table">The table to append.</param>
public void AppendTable(IFragment copyFromFrag, WP.Table table)
{
// Deep clone the run b/c of its tree of properties and to maintain styles.
this.DocBody.AppendChild(table.CloneNode(true));
this.DocBody.AppendChild(CloneElement(copyFromFrag, table));
}

/// <summary>
/// Append a paragraph to the doc fragment.
/// </summary>
public void AppendParagraph(WP.Paragraph para)
/// <param name="copyFromFrag">If the paragraph contains pictures, then this is the fragment
/// where we copy the picture data from.</param>
/// <param name="para">The paragraph to append.</param>
public void AppendParagraph(IFragment copyFromFrag, WP.Paragraph para)
{
// Deep clone the run b/c of its tree of properties and to maintain styles.
this.DocBody.AppendChild(para.CloneNode(true));
this.DocBody.AppendChild(CloneElement(copyFromFrag, para));
}


Expand Down Expand Up @@ -487,39 +493,48 @@ public void AppendToParagraph(IFragment fragToCopy, OpenXmlElement run, bool for
lastPar.AppendChild(CloneElement(fragToCopy, run));
}

public OpenXmlElement CloneElement(IFragment fragToCopy, OpenXmlElement elem)
/// <summary>
/// Does a deep clone of the element. If there is picture data then that is cloned
/// from the copyFromFrag into 'this' frag.
/// </summary>
/// <param name="copyFromFrag">If the element contains pictures, then this is the fragment
/// where we copy the picture data from.</param>
/// <param name="elem">Element to clone.</param>
/// <returns>The cloned element.</returns>
public OpenXmlElement CloneElement(IFragment copyFromFrag, OpenXmlElement elem)
{
if (elem.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().Any())
{
return CloneImageRun(fragToCopy, elem);
return CloneImageElement(copyFromFrag, elem);
}

return elem.CloneNode(true);

}

/// <summary>
/// Clones and returns a run containing an image.
/// Clones and returns a element containing an image.
/// </summary>
public OpenXmlElement CloneImageRun(IFragment fragToCopy, OpenXmlElement run)
/// <param name="copyFromFrag">The fragment where we copy the picture data from.</param>
/// <param name="elem">Element to clone.</param>
/// <returns>The cloned element.</returns>
public OpenXmlElement CloneImageElement(IFragment copyFromFrag, OpenXmlElement elem)
{
var clonedRun = run.CloneNode(true);
clonedRun.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().ToList().ForEach(
var clonedElem = elem.CloneNode(true);
clonedElem.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().ToList().ForEach(
blip =>
{
var newRelation =
CopyImage(DocFrag, blip.Embed, ((DocFragment)fragToCopy).DocFrag);
CopyImage(DocFrag, blip.Embed, ((DocFragment)copyFromFrag).DocFrag);
// Update the relationship ID in the cloned blip element.
blip.Embed = newRelation;
});
clonedRun.Descendants<DocumentFormat.OpenXml.Vml.ImageData>().ToList().ForEach(
clonedElem.Descendants<DocumentFormat.OpenXml.Vml.ImageData>().ToList().ForEach(
imageData =>
{
var newRelation = CopyImage(DocFrag, imageData.RelationshipId, ((DocFragment)fragToCopy).DocFrag);
var newRelation = CopyImage(DocFrag, imageData.RelationshipId, ((DocFragment)copyFromFrag).DocFrag);
// Update the relationship ID in the cloned image data element.
imageData.RelationshipId = newRelation;
});
return clonedRun;
return clonedElem;
}

/// <summary>
Expand Down Expand Up @@ -970,11 +985,7 @@ public IFragment AddSenseData(ConfigurableDictionaryNode config, IFragment sense

if (inAPara)
{
List<OpenXmlElement> elements = SeparateIntoFirstLevelElements(newPara, senseContent as DocFragment, config);
foreach (OpenXmlElement elem in elements)
{
senseData.DocBody.Append(elem);
}
SeparateIntoFirstLevelElements(senseData, newPara, senseContent as DocFragment, config);
}
else
{
Expand Down Expand Up @@ -1017,11 +1028,7 @@ config.DictionaryNodeOptions is IParaOption &&

if (newPara != null)
{
List<OpenXmlElement> elements = SeparateIntoFirstLevelElements(newPara, content as DocFragment, config);
foreach (OpenXmlElement elem in elements)
{
collData.DocBody.Append(elem);
}
SeparateIntoFirstLevelElements(collData, newPara, content as DocFragment, config);
}
else
{
Expand Down Expand Up @@ -1429,14 +1436,14 @@ public void AddEntryData(IFragmentWriter writer, List<ConfiguredLcmGenerator.Con
break;

case WP.Table table:
wordWriter.WordFragment.AppendTable(table);
wordWriter.WordFragment.AppendTable(frag, table);

// Start a new paragraph with the next run to maintain the correct position of the table.
wordWriter.ForceNewParagraph = true;
break;

case WP.Paragraph para:
wordWriter.WordFragment.AppendParagraph(para);
wordWriter.WordFragment.AppendParagraph(frag, para);

// Start a new paragraph with the next run so that it uses the correct style.
wordWriter.ForceNewParagraph = true;
Expand Down Expand Up @@ -2252,17 +2259,14 @@ public void AddRunStyle(IFragment frag, string nodeStyleName, string displayName
/// If we encounter one of these then end the paragraph and add the un-nestable type at the
/// same level. If we later encounter nestable types then a continuation paragraph will be created.
/// </summary>
/// <param name="outputParagraph">The first paragraph that will be returned. The content will be added
/// <param name="copyToFrag">The fragment where the new elements will be added.</param>
/// <param name="firstParagraph">The first paragraph that will be added to 'copyToFrag'. Content from contentToAdd will be added
/// to this paragraph until a un-nestable type is encountered.</param>
/// <param name="contentToAdd">The content to add either to the paragraph or at the same level as the paragraph.</param>
/// <returns>A list of elements that contain the original outputParagraph and the contentToAdd. The contentToAdd
/// might all be added to the outputParagraph, or it might also result in additional un-nestable types being returned
/// in the list.</returns>
public List<OpenXmlElement> SeparateIntoFirstLevelElements(WP.Paragraph outputParagraph, DocFragment contentToAdd, ConfigurableDictionaryNode node)
public void SeparateIntoFirstLevelElements(DocFragment copyToFrag, WP.Paragraph firstParagraph, DocFragment contentToAdd, ConfigurableDictionaryNode node)
{
List<OpenXmlElement> retList = new List<OpenXmlElement>();
bool continuationParagraph = false;
var workingParagraph = outputParagraph;
var workingParagraph = firstParagraph;
var elements = ((DocFragment)contentToAdd).DocBody.Elements();
foreach (OpenXmlElement elem in elements)
{
Expand All @@ -2272,30 +2276,28 @@ public List<OpenXmlElement> SeparateIntoFirstLevelElements(WP.Paragraph outputPa
// End the current working paragraph and add it to the list.
if (EndParagraph(workingParagraph, node, continuationParagraph))
{
retList.Add(workingParagraph);
copyToFrag.DocBody.AppendChild(workingParagraph);
}

// Add the un-nestable element.
retList.Add(elem.CloneNode(true));
copyToFrag.DocBody.AppendChild(copyToFrag.CloneElement(contentToAdd, elem));

// Start a new working paragraph.
continuationParagraph = true;
workingParagraph = new WP.Paragraph();
}
else
{
workingParagraph.AppendChild(contentToAdd.CloneElement(contentToAdd, elem));
workingParagraph.AppendChild(copyToFrag.CloneElement(contentToAdd, elem));
}
}

// If the working paragraph contains content then add it's style and add
// it to the return list.
if (EndParagraph(workingParagraph, node, continuationParagraph))
{
retList.Add(workingParagraph);
copyToFrag.DocBody.AppendChild(workingParagraph);
}

return retList;
}

/// <summary>
Expand Down
Loading