docxtor2 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +2 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +6 -0
  7. data/.wrong +1 -0
  8. data/Gemfile +18 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +71 -0
  11. data/Rakefile +7 -0
  12. data/TODO.md +2 -0
  13. data/docxtor2.gemspec +32 -0
  14. data/lib/docxtor2.rb +39 -0
  15. data/lib/docxtor2/block_evaluator.rb +13 -0
  16. data/lib/docxtor2/constants.rb +4 -0
  17. data/lib/docxtor2/content_builder.rb +29 -0
  18. data/lib/docxtor2/document_builder.rb +19 -0
  19. data/lib/docxtor2/element_list.rb +26 -0
  20. data/lib/docxtor2/generator.rb +12 -0
  21. data/lib/docxtor2/known/aliases.rb +11 -0
  22. data/lib/docxtor2/known/mappings.rb +31 -0
  23. data/lib/docxtor2/known/parts.rb +9 -0
  24. data/lib/docxtor2/known/path.rb +11 -0
  25. data/lib/docxtor2/known/styles.rb +10 -0
  26. data/lib/docxtor2/known/templates.rb +7 -0
  27. data/lib/docxtor2/object_utils.rb +7 -0
  28. data/lib/docxtor2/package.rb +33 -0
  29. data/lib/docxtor2/package/document.rb +28 -0
  30. data/lib/docxtor2/package/document/element.rb +89 -0
  31. data/lib/docxtor2/package/document/heading.rb +11 -0
  32. data/lib/docxtor2/package/document/page_break.rb +16 -0
  33. data/lib/docxtor2/package/document/paragraph.rb +90 -0
  34. data/lib/docxtor2/package/document/table_of_contents.rb +90 -0
  35. data/lib/docxtor2/package/part.rb +10 -0
  36. data/lib/docxtor2/template_parser.rb +42 -0
  37. data/lib/docxtor2/version.rb +3 -0
  38. data/spec/docxtor2/content_builder_spec.rb +24 -0
  39. data/spec/docxtor2/docxtor2_spec.rb +13 -0
  40. data/spec/docxtor2/package/document/element_spec.rb +20 -0
  41. data/spec/docxtor2/package/document/heading_spec.rb +9 -0
  42. data/spec/docxtor2/package/document/paragraph_spec.rb +56 -0
  43. data/spec/docxtor2/package/document/table_of_contents_spec.rb +18 -0
  44. data/spec/docxtor2/package/document_spec.rb +13 -0
  45. data/spec/docxtor2/package/part_spec.rb +16 -0
  46. data/spec/docxtor2/package_spec.rb +37 -0
  47. data/spec/docxtor2/prerequisites_spec.rb +9 -0
  48. data/spec/docxtor2/support/contexts/integration_context.rb +6 -0
  49. data/spec/docxtor2/support/contexts/xml_builder_context.rb +11 -0
  50. data/spec/docxtor2/support/examples/.gitkeep +0 -0
  51. data/spec/docxtor2/support/matchers/wordprocessingml_matchers.rb +42 -0
  52. data/spec/docxtor2/support/matchers/xpath_matchers.rb +46 -0
  53. data/spec/docxtor2/template_parser_spec.rb +18 -0
  54. data/spec/spec_helper.rb +35 -0
  55. data/templates/.gitkeep +0 -0
  56. data/templates/default/[Content_Types].xml +16 -0
  57. data/templates/default/_rels/.rels +4 -0
  58. data/templates/default/word/_rels/document.xml.rels +13 -0
  59. data/templates/default/word/endnotes.xml +17 -0
  60. data/templates/default/word/fontTable.xml +31 -0
  61. data/templates/default/word/footer1.xml +35 -0
  62. data/templates/default/word/footer2.xml +48 -0
  63. data/templates/default/word/footnotes.xml +17 -0
  64. data/templates/default/word/numbering.xml +212 -0
  65. data/templates/default/word/settings.xml +107 -0
  66. data/templates/default/word/styles.xml +368 -0
  67. data/templates/default/word/theme/theme1.xml +2 -0
  68. data/templates/default/word/websettings.xml +4 -0
  69. metadata +212 -0
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Docxtor2, "#generate" do
4
+ context "when supplied all the same parameters that Generator takes" do
5
+ it 'does not throw errors' do
6
+ deny { rescuing {
7
+ Docxtor2.generate do
8
+ p "Paragraph"
9
+ end
10
+ } }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Document::Element do
5
+ include_context "xmlbuilder" do
6
+
7
+ subject {
8
+ render(Package::Document::Element, :style => 1) do
9
+ write_element(:p) do
10
+ write_element(:r)
11
+ end
12
+ end
13
+ }
14
+
15
+ it 'renders element with attributes' do
16
+ subject.should contain_paragraph_run
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Document::Heading do
5
+ include_context 'xmlbuilder' do
6
+ #it 'renders heading style'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Document::Paragraph do
5
+ include_context 'xmlbuilder' do
6
+
7
+ subject {
8
+ render(Package::Document::Paragraph, "text1", :b => true) do
9
+ style 123
10
+ spacing :before => 80, :after => 240
11
+ font_size 32
12
+ font_size_complex 30
13
+ indent :start => 720
14
+ i; u
15
+
16
+ w "text2"; br; w "text3"
17
+ end
18
+ }
19
+
20
+ it 'contains reference to style' do
21
+ subject.should contain_element_style(:p)
22
+ end
23
+
24
+ it 'contains spacing property' do
25
+ subject.should contain_element_property(:p, :spacing)
26
+ end
27
+
28
+ it 'contains font size property' do
29
+ subject.should contain_element_property(:p, :sz)
30
+ end
31
+
32
+ it 'contains complex font size property' do
33
+ subject.should contain_element_property(:p, :szCs)
34
+ end
35
+
36
+ it 'contains indentiation property' do
37
+ subject.should contain_element_property(:p, :ind)
38
+ end
39
+
40
+ context 'nested run' do
41
+ it 'is bold' do
42
+ subject.should contain_element_property(:r, :b)
43
+ end
44
+
45
+ it 'is italic' do
46
+ subject.should contain_element_property(:r, :i)
47
+ end
48
+
49
+ it 'is underlined' do
50
+ subject.should contain_element_property(:r, :u)
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Document::TableOfContents do
5
+ include_context 'xmlbuilder' do
6
+
7
+ subject { render(Package::Document::TableOfContents, 'Contents') }
8
+
9
+ it 'contains gallery of document parts' do
10
+ subject.should contain_gallery_of_document_parts
11
+ end
12
+
13
+ it 'contains heading text' do
14
+ subject.should contain_sdt_content_heading
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Document do
5
+ include WordprocessingMLMatchers
6
+
7
+ subject { Package::Document.new('content', DOCUMENT_XML_PATH) }
8
+
9
+ it 'contains body' do
10
+ subject.content.should contain_body
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package::Part do
5
+ context "given filename and content" do
6
+ subject { Package::Part.new("filename", "content") }
7
+
8
+ it 'returns filename' do
9
+ expect { subject.filename == "filename" }
10
+ end
11
+ it 'returns content' do
12
+ expect { subject.content == "content" }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe Package do
5
+ subject { Package.new({}, Package::Document.new('content', DOCUMENT_XML_PATH)) }
6
+
7
+ include_context 'integration' do
8
+ context "given filepath and source document" do
9
+ it 'saves to file' do
10
+ subject.save(docx)
11
+
12
+ expect { File.exists?(docx) }
13
+ deny { rescuing { File.delete(docx) } }
14
+ end
15
+ end
16
+
17
+ context 'after serialization' do
18
+ it 'contains data' do
19
+ string_io = subject.to_stream
20
+ expect { string_io.size > 0 }
21
+ end
22
+
23
+ it 'contains document part' do
24
+ string_io = subject.to_stream
25
+ istream = Zip::ZipInputStream.open_buffer(string_io)
26
+
27
+ deny { rescuing {
28
+ document_entry = istream.get_next_entry
29
+
30
+ expect { document_entry != nil }
31
+ expect { document_entry.name == DOCUMENT_XML_PATH }
32
+ } }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Docxtor2 do
4
+ context 'prerequisites' do
5
+ it 'has a version number' do
6
+ expect { Docxtor2::VERSION != nil }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module Docxtor2
2
+ shared_context 'integration' do
3
+ let(:template) { Known::Templates::DEFAULT }
4
+ let(:docx) { File.join(Known::Path::TMP, 'test.docx') }
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ module Docxtor2
2
+ shared_context 'xmlbuilder' do
3
+ include WordprocessingMLMatchers
4
+
5
+ def render(klass, *args, &block)
6
+ builder = Builder::XmlMarkup.new
7
+ klass.new(*args, &block).render(builder)
8
+ builder.target!
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('xpath_matchers', File.dirname(__FILE__))
3
+
4
+ module WordprocessingMLMatchers
5
+ extend RSpec::Matchers::DSL
6
+ include XPathMatchers
7
+
8
+ def contain_body
9
+ exist_xpath('//w:document/w:body')
10
+ end
11
+
12
+ def contain_paragraph_text
13
+ exist_xpath('//w:p/w:r/w:t')
14
+ end
15
+
16
+ def contain_paragraph_run
17
+ exist_xpath('//w:p/w:r')
18
+ end
19
+
20
+ def contain_element_property(el, prop)
21
+ exist_xpath("//w:#{el}/w:#{el}Pr/w:#{prop}")
22
+ end
23
+
24
+ def contain_element_style(el)
25
+ contain_element_property(el, 'pStyle')
26
+ end
27
+
28
+ # TODO: These a not the same, fix it
29
+
30
+ def contain_gallery_of_document_parts
31
+ exist_xpath('//w:sdt/w:sdtPr/w:docPartObj/w:docPartGallery')
32
+ end
33
+
34
+ def contain_sdt_content_heading
35
+ exist_xpath('//w:sdt/w:sdtPr/w:docPartObj/w:docPartGallery')
36
+ end
37
+
38
+ def contain_table_of_contents
39
+ contain_gallery_of_document_parts &&
40
+ contain_sdt_content_heading
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ module XPathMatchers
2
+ extend RSpec::Matchers::DSL
3
+ include RSpecXML::XMLMatchers
4
+
5
+ EXPR_PREFIX = '//'
6
+ LOCAL_NAME_EXPR = "*[local-name()='%s']"
7
+ ATTRIBUTE_SEPARATORS = ['|', '&', 'and', 'or']
8
+
9
+ matcher :exist_xpath do |xpath|
10
+ match do |xml|
11
+ xml.should have_xpath(ignore_namespaces(xpath))
12
+ end
13
+ description do
14
+ "xpath #{xpath} exist"
15
+ end
16
+
17
+ failure_message_for_should do |actual|
18
+ "expected xpath #{expected} to exist in #{actual}"
19
+ end
20
+
21
+ # TODO: Make it work with attributes
22
+ # Typical cases are:
23
+ #
24
+ # //person[@id='abc123']/@*[name()='weight' or name()='haircolor']
25
+ # //person[@id='abc123']/(@haircolor|@weight)`
26
+ # [@id='abc123']
27
+ # @*[name()='weight' or name()='haircolor']
28
+ #
29
+ # This should work, try it:
30
+ #
31
+ # //*[local-name()='a'][*[local-name()='aCode']='aaa']
32
+
33
+ # takes smth like //w:p/w:r and
34
+ # returns //*[local-name()='p']/*[local-name()='r]
35
+ def ignore_namespaces(xpath)
36
+ expressions = xpath.sub(EXPR_PREFIX, '').
37
+ split('/').map { |expr| to_local_name(expr) }.join('/')
38
+ EXPR_PREFIX + expressions
39
+ end
40
+
41
+ def to_local_name(expr)
42
+ element = expr.split(':').last
43
+ LOCAL_NAME_EXPR % element
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Docxtor2
4
+ describe TemplateParser do
5
+ include_context 'integration' do
6
+ subject { TemplateParser.new(template) }
7
+
8
+ it 'finds exact count of template files' do
9
+ expected = Dir.chdir(template) {
10
+ Dir[SEARCH_PATTERN].
11
+ delete_if { |file| File.directory?(file) }.
12
+ length
13
+ }
14
+ expect { subject.parts.length == expected }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ if ENV["COVERAGE"]
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'rspec'
7
+ require 'rspec-xml'
8
+
9
+ require 'wrong/adapters/rspec'
10
+ Wrong.config.alias_assert :expect, :override => true
11
+
12
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
13
+
14
+ require 'docxtor2'
15
+
16
+ if ENV["TRAVIS"]
17
+ require 'coveralls'
18
+ Coveralls.wear!
19
+ end
20
+
21
+ ['matchers', 'contexts', 'examples'].each do |dir|
22
+ dir_pattern = File.join(File.dirname(__FILE__),
23
+ 'docxtor2', 'support', dir, '**', '*.rb')
24
+ Dir[File.expand_path(dir_pattern)].each { |f| require f }
25
+ end
26
+
27
+ RSpec.configure do |config|
28
+ config.before(:all) do
29
+ Dir.mkdir(Docxtor2::Known::Path::TMP, 0700)
30
+ end
31
+
32
+ config.after(:all) do
33
+ FileUtils.rm_rf(Docxtor2::Known::Path::TMP)
34
+ end
35
+ end
File without changes
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
3
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" PartName="/word/footnotes.xml"/>
4
+ <Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
5
+ <Default ContentType="application/xml" Extension="xml"/>
6
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" PartName="/word/document.xml"/>
7
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" PartName="/word/numbering.xml"/>
8
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" PartName="/word/styles.xml"/>
9
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" PartName="/word/endnotes.xml"/>
10
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" PartName="/word/settings.xml"/>
11
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" PartName="/word/footer2.xml"/>
12
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" PartName="/word/footer1.xml"/>
13
+ <Override ContentType="application/vnd.openxmlformats-officedocument.theme+xml" PartName="/word/theme/theme1.xml"/>
14
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" PartName="/word/fontTable.xml"/>
15
+ <Override ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" PartName="/word/webSettings.xml"/>
16
+ </Types>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
3
+ <Relationship Id="rId1" Target="word/document.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"/>
4
+ </Relationships>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
3
+ <Relationship Id="rId8" Target="footer2.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"/>
4
+ <Relationship Id="rId3" Target="settings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"/>
5
+ <Relationship Id="rId7" Target="footer1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"/>
6
+ <Relationship Id="rId2" Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"/>
7
+ <Relationship Id="rId1" Target="numbering.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering"/>
8
+ <Relationship Id="rId6" Target="endnotes.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"/>
9
+ <Relationship Id="rId5" Target="footnotes.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"/>
10
+ <Relationship Id="rId10" Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"/>
11
+ <Relationship Id="rId4" Target="webSettings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings"/>
12
+ <Relationship Id="rId9" Target="fontTable.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"/>
13
+ </Relationships>
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <w:endnotes xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
3
+ <w:endnote w:id="0" w:type="separator">
4
+ <w:p w:rsidR="00F8394C" w:rsidRDefault="00F8394C">
5
+ <w:r>
6
+ <w:separator/>
7
+ </w:r>
8
+ </w:p>
9
+ </w:endnote>
10
+ <w:endnote w:id="1" w:type="continuationSeparator">
11
+ <w:p w:rsidR="00F8394C" w:rsidRDefault="00F8394C">
12
+ <w:r>
13
+ <w:continuationSeparator/>
14
+ </w:r>
15
+ </w:p>
16
+ </w:endnote>
17
+ </w:endnotes>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <w:fonts xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
3
+ <w:font w:name="Times New Roman">
4
+ <w:panose1 w:val="02020603050405020304"/>
5
+ <w:charset w:val="CC"/>
6
+ <w:family w:val="roman"/>
7
+ <w:pitch w:val="variable"/>
8
+ <w:sig w:csb0="000001FF" w:csb1="00000000" w:usb0="E0002AFF" w:usb1="C0007841" w:usb2="00000009" w:usb3="00000000"/>
9
+ </w:font>
10
+ <w:font w:name="Arial">
11
+ <w:panose1 w:val="020B0604020202020204"/>
12
+ <w:charset w:val="CC"/>
13
+ <w:family w:val="swiss"/>
14
+ <w:pitch w:val="variable"/>
15
+ <w:sig w:csb0="000001FF" w:csb1="00000000" w:usb0="E0002AFF" w:usb1="C0007843" w:usb2="00000009" w:usb3="00000000"/>
16
+ </w:font>
17
+ <w:font w:name="Calibri">
18
+ <w:panose1 w:val="020F0502020204030204"/>
19
+ <w:charset w:val="CC"/>
20
+ <w:family w:val="swiss"/>
21
+ <w:pitch w:val="variable"/>
22
+ <w:sig w:csb0="0000019F" w:csb1="00000000" w:usb0="E10002FF" w:usb1="4000ACFF" w:usb2="00000009" w:usb3="00000000"/>
23
+ </w:font>
24
+ <w:font w:name="Cambria">
25
+ <w:panose1 w:val="02040503050406030204"/>
26
+ <w:charset w:val="CC"/>
27
+ <w:family w:val="roman"/>
28
+ <w:pitch w:val="variable"/>
29
+ <w:sig w:csb0="0000019F" w:csb1="00000000" w:usb0="A00002EF" w:usb1="4000004B" w:usb2="00000000" w:usb3="00000000"/>
30
+ </w:font>
31
+ </w:fonts>