docxedit 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,5 @@
1
1
  module DocxEdit
2
2
  class ContentBlock
3
-
4
3
  attr_accessor :content
5
4
 
6
5
  def initialize(xml, content)
@@ -9,6 +8,10 @@ module DocxEdit
9
8
  @content = content
10
9
  end
11
10
 
11
+ def clone
12
+ result = ContentBlock.new(rclone_xml(@xml), @content_key)
13
+ end
14
+
12
15
  def xml
13
16
  unless(@content_key == @content)
14
17
  @node = REXML::XPath.first(@xml, "//*[text()='#{@content_key}']]")
@@ -17,5 +20,17 @@ module DocxEdit
17
20
  end
18
21
  return @xml
19
22
  end
23
+
24
+ private
25
+
26
+ def rclone_xml(node)
27
+ new_node = node.clone
28
+ unless node.node_type == :text
29
+ node.children.each do |c|
30
+ new_node << rclone_xml(c)
31
+ end
32
+ end
33
+ return new_node
34
+ end
20
35
  end
21
36
  end
@@ -1,19 +1,26 @@
1
1
  require 'zip/zip'
2
2
  require "rexml/document"
3
+ require 'tempfile'
3
4
  require_relative 'content_block'
4
5
 
5
6
  module DocxEdit
6
7
  class Docx
7
- attr_reader :zip_file, :xml_document
8
+ attr_reader :zip_file, :xml_document, :xml_headers, :xml_footers
8
9
 
9
10
  def initialize(path)
10
11
  @zip_file = Zip::ZipFile.new(path)
11
- @xml_document = REXML::Document.new(read_content)
12
+ bind_contents
13
+ end
14
+
15
+ def files
16
+ return @xml_headers + @xml_footers + [@xml_document]
12
17
  end
13
18
 
14
19
  def contains?(text)
15
- REXML::XPath.each @xml_document, XPATH_ALL_TEXT_NODE do |n|
16
- return true if n.text =~ text
20
+ files.each do |f|
21
+ REXML::XPath.each f, XPATH_ALL_TEXT_NODE do |n|
22
+ return true if n.text =~ text
23
+ end
17
24
  end
18
25
  return false
19
26
  end
@@ -24,14 +31,18 @@ module DocxEdit
24
31
  end
25
32
 
26
33
  def replace(reg_to_match, replacement)
27
- REXML::XPath.each @xml_document, XPATH_ALL_TEXT_NODE do |n|
28
- n.text = n.text.gsub(reg_to_match, replacement)
34
+ files.each do |f|
35
+ REXML::XPath.each f, XPATH_ALL_TEXT_NODE do |n|
36
+ n.text = n.text.gsub(reg_to_match, replacement)
37
+ end
29
38
  end
30
39
  end
31
40
 
32
41
  def find_block_with_content(exact_content_string)
33
- node = REXML::XPath.first(@xml_document, "//w:p[descendant-or-self::*[text()='#{exact_content_string}']]")
34
- return ContentBlock.new(node, exact_content_string)
42
+ files.each do
43
+ node = REXML::XPath.first(@xml_document, "//w:p[descendant-or-self::*[text()='#{exact_content_string}']]")
44
+ return ContentBlock.new(node, exact_content_string) unless node.nil?
45
+ end
35
46
  end
36
47
 
37
48
  # insert the xml of a content block :before or :after the anchor_block
@@ -54,17 +65,64 @@ module DocxEdit
54
65
  DOCUMENT_FILE_PATH = 'word/document.xml'
55
66
  XPATH_ALL_TEXT_NODE = "//*[text()]"
56
67
 
57
- def read_content()
58
- return text = @zip_file.read(DOCUMENT_FILE_PATH)
68
+ def bind_contents
69
+ @xml_document = REXML::Document.new(@zip_file.read(DOCUMENT_FILE_PATH))
70
+ @xml_headers = []
71
+ @xml_footers = []
72
+ REXML::Document.new(@zip_file.read(DOCUMENT_FILE_PATH))
73
+
74
+ idx = 1
75
+ src = read_or_nil("word/header#{idx}.xml")
76
+ while(!src.nil?) do
77
+ @xml_headers << REXML::Document.new(src)
78
+ idx = idx + 1
79
+ src = read_or_nil("word/header#{idx}.xml")
80
+ end
81
+
82
+ idx = 1
83
+ src = read_or_nil("word/footer#{idx}.xml")
84
+ while(!src.nil?) do
85
+ @xml_headers << REXML::Document.new(src)
86
+ idx = idx + 1
87
+ src = read_or_nil("word/footer#{idx}.xml")
88
+ end
89
+ end
90
+
91
+
92
+ def read_or_nil(name)
93
+ return @zip_file.read(name) rescue return nil
94
+ end
95
+
96
+ def write_entry(zip_output_stream, entry_name, xml_doc)
97
+ zip_output_stream.put_next_entry(entry_name)
98
+ output = ""
99
+ xml_doc.write(output, 0)
100
+ zip_output_stream.print output
59
101
  end
60
102
 
61
103
  def write_content()
62
- @zip_file.get_output_stream(DOCUMENT_FILE_PATH) do |input|
63
- output = ""
64
- @xml_document.write(output, 0)
65
- input.write output
104
+ temp_file = Tempfile.new('docxedit-')
105
+ Zip::ZipOutputStream.open(temp_file.path) do |zos|
106
+ @zip_file.entries.each do |e|
107
+ unless e.name == DOCUMENT_FILE_PATH || e.name =~ /word\/(header|footer)[0-9]+\.xml/
108
+ zos.put_next_entry(e.name)
109
+ zos.print e.get_input_stream.read
110
+ end
111
+ end
112
+
113
+ write_entry(zos, DOCUMENT_FILE_PATH, @xml_document)
114
+ (0 .. @xml_headers.size - 1).each do |idx|
115
+ write_entry zos, "word/header#{idx + 1}.xml", @xml_headers[idx]
116
+ end
117
+ (0 .. @xml_footers.size - 1).each do |idx|
118
+ write_entry zos, "word/footer#{idx + 1}.xml", @xml_footers[idx]
119
+ end
66
120
  end
67
- @zip_file.commit
121
+
122
+ path = @zip_file.name
123
+ FileUtils.rm(path)
124
+ FileUtils.mv(temp_file.path, path)
125
+ @zip_file = Zip::ZipFile.new(path)
68
126
  end
69
127
  end
70
128
  end
@@ -1,3 +1,3 @@
1
1
  module DocxEdit
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docxedit
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 5
10
+ version: 0.0.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Olivier Amblet
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-10 00:00:00 +01:00
18
+ date: 2011-02-14 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rspec
22
+ name: rubyzip
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
@@ -30,8 +30,22 @@ dependencies:
30
30
  segments:
31
31
  - 0
32
32
  version: "0"
33
- type: :development
33
+ type: :runtime
34
34
  version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
35
49
  description: minimal .docx file editor.
36
50
  email: olivier@amblet.net
37
51
  executables: []