Class: Docx::Elements::Containers::Paragraph
- Inherits:
-
Object
- Object
- Docx::Elements::Containers::Paragraph
- Defined in:
- lib/docx/containers/paragraph.rb
Constant Summary
Constants included from Element
Instance Attribute Summary
Attributes included from Element
Class Method Summary collapse
Instance Method Summary collapse
- #aligned_center? ⇒ Boolean
- #aligned_left? ⇒ Boolean
- #aligned_right? ⇒ Boolean
-
#each_text_run ⇒ Object
Iterate over each text run within a paragraph.
- #font_color ⇒ Object
- #font_size ⇒ Object
-
#initialize(node, document_properties = {}, doc = nil) ⇒ Paragraph
constructor
Child elements: pPr, r, fldSimple, hlink, subDoc msdn.microsoft.com/en-us/library/office/ee364458(v=office.11).aspx.
- #style ⇒ Object
- #style=(identifier) ⇒ Object (also: #style_id=)
- #style_id ⇒ Object
-
#substitute(pattern, replacement) ⇒ Object
Substitute text within the paragraph, even when a match spans multiple text runs (e.g. a “{placeholder}” that Word split across several runs, such as ““rst_na”, “me}”).
-
#text=(content) ⇒ Object
Set text of paragraph.
-
#text_runs ⇒ Object
Array of text runs contained within paragraph.
-
#to_html ⇒ Object
Return paragraph as a <p></p> HTML fragment with formatting based on properties.
-
#to_s ⇒ Object
(also: #text)
Return text of paragraph.
Methods included from Element
#append_to, #at_xpath, #copy, #html_tag, included, #insert_after, #insert_before, #parent, #parent_paragraph, #prepend_to, #xpath
Methods included from Container
#blank!, #properties, #remove!
Constructor Details
#initialize(node, document_properties = {}, doc = nil) ⇒ Paragraph
Child elements: pPr, r, fldSimple, hlink, subDoc msdn.microsoft.com/en-us/library/office/ee364458(v=office.11).aspx
18 19 20 21 22 23 24 |
# File 'lib/docx/containers/paragraph.rb', line 18 def initialize(node, document_properties = {}, doc = nil) @node = node @properties_tag = 'pPr' @document_properties = document_properties @font_size = @document_properties[:font_size] @document = doc end |
Class Method Details
.tag ⇒ Object
11 12 13 |
# File 'lib/docx/containers/paragraph.rb', line 11 def self.tag 'p' end |
Instance Method Details
#aligned_center? ⇒ Boolean
129 130 131 |
# File 'lib/docx/containers/paragraph.rb', line 129 def aligned_center? alignment == 'center' end |
#aligned_left? ⇒ Boolean
121 122 123 |
# File 'lib/docx/containers/paragraph.rb', line 121 def aligned_left? ['left', nil].include?(alignment) end |
#aligned_right? ⇒ Boolean
125 126 127 |
# File 'lib/docx/containers/paragraph.rb', line 125 def aligned_right? alignment == 'right' end |
#each_text_run ⇒ Object
Iterate over each text run within a paragraph
64 65 66 |
# File 'lib/docx/containers/paragraph.rb', line 64 def each_text_run text_runs.each { |tr| yield(tr) } end |
#font_color ⇒ Object
141 142 143 144 |
# File 'lib/docx/containers/paragraph.rb', line 141 def font_color color_tag = @node.xpath('w:r//w:rPr//w:color').first color_tag ? color_tag.attributes['val']&.value : nil end |
#font_size ⇒ Object
133 134 135 136 137 138 139 |
# File 'lib/docx/containers/paragraph.rb', line 133 def font_size size_attribute = @node.at_xpath('w:pPr//w:sz//@w:val') return @font_size unless size_attribute size_attribute.value.to_i / 2 end |
#style ⇒ Object
146 147 148 149 150 151 |
# File 'lib/docx/containers/paragraph.rb', line 146 def style return nil unless @document @document.style_name_of(style_id) || @document.default_paragraph_style end |
#style=(identifier) ⇒ Object Also known as: style_id=
157 158 159 160 161 |
# File 'lib/docx/containers/paragraph.rb', line 157 def style=(identifier) id = @document.styles_configuration.style_of(identifier).id style_property.set_attribute('w:val', id) end |
#style_id ⇒ Object
153 154 155 |
# File 'lib/docx/containers/paragraph.rb', line 153 def style_id style_property.get_attribute('w:val') end |
#substitute(pattern, replacement) ⇒ Object
Substitute text within the paragraph, even when a match spans multiple text runs (e.g. a “{placeholder}” that Word split across several runs, such as ““rst_na”, “me}”). The per-run TextRun#substitute cannot match those, but this can, because it joins the runs first.
The matched region is collapsed into the first run it touches, so that run’s formatting is kept while the other spanned runs are emptied; runs outside the match are left untouched.
pattern may be a String or a Regexp; replacement follows String#sub semantics, so capture-group backreferences (e.g. ‘1’) work with a Regexp.
# given a paragraph reading "Hello {{first_name}}!"
paragraph.substitute('{{first_name}}', 'Jane') # => "Hello Jane!"
paragraph.substitute(/\{\{(\w+)\}\}/, 'value of \1')
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/docx/containers/paragraph.rb', line 85 def substitute(pattern, replacement) search_from = 0 loop do runs = text_runs break if runs.empty? offsets = [] cursor = 0 runs.each do |run| offsets << cursor cursor += run.text.length end full_text = runs.map(&:text).join match = full_text.match(pattern, search_from) break unless match break if match.end(0) == match.begin(0) # ignore empty matches match_start = match.begin(0) match_end = match.end(0) # exclusive first = offsets.rindex { |offset| offset <= match_start } last = offsets.rindex { |offset| offset < match_end } combined = runs[first..last].map(&:text).join local_start = match_start - offsets[first] local_end = match_end - offsets[first] replaced = combined[local_start...local_end].sub(pattern, replacement) runs[first].text = combined[0...local_start] + replaced + combined[local_end..-1] ((first + 1)..last).each { |index| runs[index].text = '' } # advance past the inserted replacement so it is not re-matched search_from = match_start + replaced.length end self end |
#text=(content) ⇒ Object
Set text of paragraph
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/docx/containers/paragraph.rb', line 27 def text=(content) if text_runs.size == 1 text_runs.first.text = content elsif text_runs.size == 0 new_r = TextRun.create_within(self) new_r.text = content else text_runs.each {|r| r.node.remove } new_r = TextRun.create_within(self) new_r.text = content end end |
#text_runs ⇒ Object
Array of text runs contained within paragraph
59 60 61 |
# File 'lib/docx/containers/paragraph.rb', line 59 def text_runs @node.xpath('w:r|w:hyperlink').map { |r_node| Containers::TextRun.new(r_node, @document_properties) } end |
#to_html ⇒ Object
Return paragraph as a <p></p> HTML fragment with formatting based on properties.
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/docx/containers/paragraph.rb', line 46 def to_html html = +'' text_runs.each do |text_run| html << text_run.to_html end styles = { 'font-size' => "#{font_size}pt" } styles['color'] = "##{font_color}" if font_color styles['text-align'] = alignment if alignment html_tag(:p, content: html, styles: styles) end |
#to_s ⇒ Object Also known as: text
Return text of paragraph
41 42 43 |
# File 'lib/docx/containers/paragraph.rb', line 41 def to_s text_runs.map(&:text).join('') end |