From eadf008cdf85611b551b1e99d7ad39652e5993b8 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Sun, 18 Oct 2026 01:36:42 +0900 Subject: [PATCH] Preserve leading/trailing spaces written to w:t (#187) Elements::Text#content= never set xml:space="preserve", so when a write left a w:t starting or ending with a space (e.g. substitute producing "Jane "), Word dropped the space and showed "Janeend". Set the attribute whenever the new content has surrounding whitespace. Co-Authored-By: Claude Opus 5.5 --- lib/docx/elements/text.rb | 2 ++ spec/docx/elements/text_spec.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/docx/elements/text.rb b/lib/docx/elements/text.rb index fb89401..dcac793 100644 --- a/lib/docx/elements/text.rb +++ b/lib/docx/elements/text.rb @@ -13,6 +13,8 @@ def content def content=(args) @node.content = args + # Without xml:space="preserve", Word drops leading and trailing spaces. + @node['xml:space'] = 'preserve' if args.to_s.match?(/\A\s|\s\z/) end def initialize(node) diff --git a/spec/docx/elements/text_spec.rb b/spec/docx/elements/text_spec.rb index c15e979..3f9fbc2 100644 --- a/spec/docx/elements/text_spec.rb +++ b/spec/docx/elements/text_spec.rb @@ -23,5 +23,33 @@ expect(node.content).to eq('world') end + + # Regression tests for #187: without xml:space="preserve", Word drops + # leading and trailing spaces of a w:t. + it 'marks the node xml:space="preserve" when the content has a trailing space' do + text.content = 'Jane ' + + expect(node.to_xml).to eq('Jane ') + end + + it 'marks the node xml:space="preserve" when the content has a leading space' do + text.content = ' end' + + expect(node.to_xml).to eq(' end') + end + + it 'does not add xml:space when the content has no surrounding whitespace' do + text.content = 'Jane' + + expect(node.to_xml).to eq('Jane') + end + + it 'keeps an existing xml:space="preserve"' do + node = w_node(' a ') + + described_class.new(node).content = 'b' + + expect(node.to_xml).to eq('b') + end end end