docxtor2 0.0.9

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.
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>