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

fix: #198 WordML MergeFields remove parent and crashes if multiple fields share parent #199

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
42 changes: 39 additions & 3 deletions lib/sablon/content.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,44 @@ def append_to(paragraph, display_node, env)
add_siblings_to(display_node.parent, pr_tag)
display_node.parent.remove
else
add_siblings_to(paragraph)
paragraph.remove
# Insert a new paragraph before this paragraph
# and add nodes to that paragraph instead. It's inserted
# before so that the order is preserved, otherwise when
# fields are processed, they will be in reverse order if
# each is added as the next sibling of the paragraph.
dummy_paragraph = Nokogiri::XML::Node.new("w:p", display_node.document)

paragraph.add_previous_sibling dummy_paragraph

# Copy rPr tag if any
pr_tag = display_node.parent.at_xpath('./w:rPr')
add_siblings_to(dummy_paragraph, pr_tag)

# Get all merge fields for the parent paragraph
merge_fields = get_merge_fields(paragraph)

# Find merge field this belongs to:
current_field_idx = merge_fields.find_index { |child| child.any? { display_node.ancestors.include?(_1) } }

# Only remove the paragraph parent if it doesn't contain any more merge fields,
# otherwise leave it in place so those merge fields dont lose their parent
paragraph.remove if current_field_idx == merge_fields.length - 1
end
end

# Get all merge fields in a node
def get_merge_fields(node)
merge_fields = []

inside_field = false
node.children.each do |field|
if field.children.any? { |child| child.name == 'fldChar' && child['w:fldCharType'] == 'begin' }
merge_fields << [field]
inside_field = true
elsif inside_field
merge_fields.last << field
inside_field = false if field.children.any? { |child| child.name == 'fldChar' && child['w:fldCharType'] == 'end' }
end
end
end

Expand Down Expand Up @@ -143,7 +179,7 @@ def add_siblings_to(node, rpr_tag = nil)
end
end

# Merges the provided properties into the run properties of the
# Merges the provided properties into the run proprties of the
# node passed in. Properties are only added if they are not already
# defined on the node itself.
def merge_rpr_tags(node, props)
Expand Down