docx_generator 0.1.0 → 0.1.1

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,9 +1,9 @@
1
- require 'docx_generator/version'
2
- require 'docx_generator/element'
3
- require 'docx_generator/word'
4
- require 'docx_generator/dsl'
5
- require 'zip/zip'
6
-
7
- # Main module of the library.
8
- module DocxGenerator
9
- end
1
+ require 'docx_generator/version'
2
+ require 'docx_generator/element'
3
+ require 'docx_generator/word'
4
+ require 'docx_generator/dsl'
5
+ require 'zip'
6
+
7
+ # Main module of the library.
8
+ module DocxGenerator
9
+ end
@@ -1,10 +1,10 @@
1
- require 'docx_generator/dsl/document'
2
- require 'docx_generator/dsl/paragraph'
3
- require 'docx_generator/dsl/text'
4
-
5
- module DocxGenerator
6
- # Namespace for the classes to be used directly by users.
7
- module DSL
8
-
9
- end
1
+ require 'docx_generator/dsl/document'
2
+ require 'docx_generator/dsl/paragraph'
3
+ require 'docx_generator/dsl/text'
4
+
5
+ module DocxGenerator
6
+ # Namespace for the classes to be used directly by users.
7
+ module DSL
8
+
9
+ end
10
10
  end
@@ -1,75 +1,84 @@
1
- module DocxGenerator
2
- module DSL
3
- class Document
4
- attr_reader :filename
5
-
6
- def initialize(filename, &block)
7
- @filename = filename + ".docx"
8
- @objects = [] # It contains all the DSL elements
9
- yield self if block
10
- end
11
-
12
- # Could be better
13
- def save
14
- content_types = generate_content_types
15
- rels = generate_rels
16
- document = generate_document
17
-
18
- File.delete(@filename) if File.exists?(@filename)
19
- Zip::ZipFile.open(@filename, Zip::ZipFile::CREATE) do |docx|
20
- docx.mkdir('_rels')
21
- docx.mkdir('word')
22
- docx.get_output_stream('[Content_Types].xml') { |f| f.puts content_types }
23
- docx.get_output_stream('_rels/.rels') { |f| f.puts rels }
24
- docx.get_output_stream('word/document.xml') { |f| f.puts document }
25
- end
26
- end
27
-
28
- def paragraph(options = {}, &block)
29
- par = DocxGenerator::DSL::Paragraph.new(options)
30
- yield par if block
31
- @objects << par
32
- end
33
-
34
- def add(*objects)
35
- objects.each do |object|
36
- @objects << object
37
- end
38
- self
39
- end
40
-
41
- private
42
-
43
- def generate_content_types
44
- <<EOF
45
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
46
- <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
47
- <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
48
- <Default Extension="xml" ContentType="application/xml"/>
49
- <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
50
- </Types>
51
- EOF
52
- end
53
-
54
- def generate_rels
55
- <<EOF
56
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
57
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
58
- <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
59
- </Relationships>
60
- EOF
61
- end
62
-
63
- def generate_document
64
- content = []
65
- @objects.each do |object|
66
- content << object.generate
67
- end
68
-
69
- '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
70
- Word::Document.new({ "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
71
- [ Word::Body.new(content) ]).to_s
72
- end
73
- end
74
- end
75
- end
1
+ module DocxGenerator
2
+ module DSL
3
+ # Represent the docx document.
4
+ class Document
5
+ # Filename of the document (without the docx extension).
6
+ attr_reader :filename
7
+
8
+ # Create a new docx document.
9
+ # @param filename [String] The filename of the docx file, without the docx extension.
10
+ def initialize(filename, &block)
11
+ @filename = filename + ".docx"
12
+ @objects = [] # It contains all the DSL elements
13
+ yield self if block
14
+ end
15
+
16
+ # Save the docx document to the target location.
17
+ def save
18
+ generate_archive(generate_content_types, generate_rels, generate_document)
19
+ end
20
+
21
+ # Add a new paragraph to the document.
22
+ # @param options [Hash] Formatting options for the paragraph. See the full list in DocxGenerator::DSL::Paragraph.
23
+ def paragraph(options = {}, &block)
24
+ par = DocxGenerator::DSL::Paragraph.new(options)
25
+ yield par if block
26
+ @objects << par
27
+ end
28
+
29
+ # Add other objects to the document.
30
+ # @param objects [Object] Objects (like paragraphs).
31
+ # @return [DocxGenerator::DSL::Document] The document object.
32
+ def add(*objects)
33
+ objects.each do |object|
34
+ @objects << object
35
+ end
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ def generate_content_types
42
+ <<EOF
43
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
44
+ <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
45
+ <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
46
+ <Default Extension="xml" ContentType="application/xml"/>
47
+ <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
48
+ </Types>
49
+ EOF
50
+ end
51
+
52
+ def generate_rels
53
+ <<EOF
54
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
55
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
56
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
57
+ </Relationships>
58
+ EOF
59
+ end
60
+
61
+ def generate_document
62
+ content = []
63
+ @objects.each do |object|
64
+ content << object.generate
65
+ end
66
+
67
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
68
+ Word::Document.new({ "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main" },
69
+ [ Word::Body.new(content) ]).to_s
70
+ end
71
+
72
+ def generate_archive(content_types, rels, document)
73
+ File.delete(@filename) if File.exists?(@filename)
74
+ Zip::File.open(@filename, Zip::File::CREATE) do |docx|
75
+ docx.mkdir('_rels')
76
+ docx.mkdir('word')
77
+ docx.get_output_stream('[Content_Types].xml') { |f| f.puts content_types }
78
+ docx.get_output_stream('_rels/.rels') { |f| f.puts rels }
79
+ docx.get_output_stream('word/document.xml') { |f| f.puts document }
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,72 +1,125 @@
1
- module DocxGenerator
2
- module DSL
3
- class Paragraph
4
- def initialize(options = {}, &block)
5
- @objects = []
6
- @options = options
7
- yield self if block
8
- end
9
-
10
- def alignment(value)
11
- @options[:alignment] = value
12
- end
13
-
14
- def no_space
15
- @objects << DocxGenerator::Word::Extensions::NoSpace.new
16
- end
17
-
18
- def text(text_fragment, options = {}, &block)
19
- text_object = DocxGenerator::DSL::Text.new(text_fragment, options)
20
- yield text_object if block
21
- @objects << text_object
22
- end
23
-
24
- def generate
25
- text_fragments = generate_text_fragments
26
- options = generate_paragraph_options
27
- if options
28
- Word::Paragraph.new({}, text_fragments.unshift(options))
29
- else
30
- Word::Paragraph.new({}, text_fragments)
31
- end
32
- end
33
-
34
- def add(*objects)
35
- objects.each do |object|
36
- @objects << object
37
- end
38
- self
39
- end
40
-
41
- private
42
- def generate_text_fragments
43
- text_fragments = []
44
- @objects.each do |object|
45
- if object.respond_to?(:generate)
46
- text_fragments << object.generate << Word::Extensions.space
47
- elsif object.class == DocxGenerator::Word::Extensions::NoSpace
48
- text_fragments.pop
49
- end
50
- end
51
- text_fragments.pop # In order to remove the last space added
52
- text_fragments
53
- end
54
-
55
- def generate_paragraph_options
56
- unless @options.empty?
57
- parsed_options = []
58
- @options.each do |option, value|
59
- parsed_options << parse_paragraph_option(option, value)
60
- end
61
- Word::ParagraphProperties.new(parsed_options)
62
- end
63
- end
64
-
65
- def parse_paragraph_option(option, value)
66
- case option
67
- when :alignment then Word::Alignment.new(value)
68
- end
69
- end
70
- end
71
- end
72
- end
1
+ module DocxGenerator
2
+ module DSL
3
+ # Represent a paragraph with formatting options
4
+ class Paragraph
5
+ # Create a new paragraph with the formatting options specified.
6
+ # The formatting properties can be passed with a Hash or they could be set by calling the methods on the object (either in the block or not).
7
+ # @param options [Hash] Formatting options.
8
+ # @option options [Boolean] alignment The alignment of the paragraph. See the specification for the complete list.
9
+ # @option options [Hash] spacing Various spacing options for the paragraph. See the specification for more details.
10
+ # @option options [Hash] indentation Various indentation properties for the paragraph. See the specification for more details.
11
+ # @option options [Array] tabs Custom tabulation stops. See the specification for more details.
12
+ def initialize(options = {}, &block)
13
+ @objects = []
14
+ @options = options
15
+ yield self if block
16
+ end
17
+
18
+ # Set the alignment of the paragraph. See the specification for more details.
19
+ # @param value [String] The alignment of the paragraph. See the specification for the complete list.
20
+ def alignment(value)
21
+ @options[:alignment] = value
22
+ end
23
+
24
+ # Set various spacing options for the paragraph. See the specification for more details.
25
+ # @param options [Hash] Various spacing options for the paragraph. See the specification for more details.
26
+ def spacing(options)
27
+ @options[:spacing] = options
28
+ end
29
+
30
+ # Set various indentation properties for the paragraph. See the specification for more details.
31
+ # @param properties [Hash] Various indentation properties for the paragraph. See the specification for more details.
32
+ def indentation(properties)
33
+ @options[:indentation] = properties
34
+ end
35
+
36
+ # Set custom tabulation stops. See the specification for more details.
37
+ # @param tab_stops [Array] Custom tabulation stops.
38
+ def tabs(tab_stops)
39
+ @options[:tabs] = tab_stops
40
+ end
41
+
42
+ # Prevent the addition of a space between two text fragments.
43
+ def no_space
44
+ @objects << DocxGenerator::Word::Extensions::NoSpace.new
45
+ end
46
+
47
+ # Add a newline
48
+ def newline
49
+ @objects << DocxGenerator::Word::Extensions::Newline.new
50
+ end
51
+
52
+ # Add a tabulation
53
+ def tab
54
+ @objects << DocxGenerator::Word::Tab.new
55
+ end
56
+
57
+ # Add a new text fragment to the paragraph.
58
+ # @param text_fragment [String] The text fragment.
59
+ # @param options [Hash] Formatting options for the text fragment. See the full list in DocxGenerator::DSL::Text.
60
+ def text(text_fragment, options = {}, &block)
61
+ text_object = DocxGenerator::DSL::Text.new(text_fragment, options)
62
+ yield text_object if block
63
+ @objects << text_object
64
+ end
65
+
66
+ # Generate the XML element objects.
67
+ # @return [DocxGenerator::Word::Paragraph] A Word::Paragraph object representing the paragraph.
68
+ def generate
69
+ text_fragments = generate_text_fragments
70
+ options = generate_paragraph_options
71
+ if options
72
+ Word::Paragraph.new({}, text_fragments.unshift(options))
73
+ else
74
+ Word::Paragraph.new({}, text_fragments)
75
+ end
76
+ end
77
+
78
+ # Add other objects to the paragraph.
79
+ # @param objects [Object] Objects (like text fragments).
80
+ # @return [DocxGenerator::DSL::Paragraph] The paragraph object.
81
+ def add(*objects)
82
+ objects.each do |object|
83
+ @objects << object
84
+ end
85
+ self
86
+ end
87
+
88
+ private
89
+ def generate_text_fragments
90
+ text_fragments = []
91
+ @objects.each do |object|
92
+ if object.class == DocxGenerator::Word::Extensions::NoSpace
93
+ text_fragments.pop
94
+ elsif object.class == DocxGenerator::Word::Extensions::Newline
95
+ text_fragments.pop
96
+ text_fragments << object.generate
97
+ elsif object.respond_to?(:generate)
98
+ text_fragments << object.generate << Word::Extensions.space
99
+ end
100
+ end
101
+ text_fragments.pop if text_fragments.last.to_s == Word::Extensions.space.to_s # In order to remove the last space added
102
+ text_fragments
103
+ end
104
+
105
+ def generate_paragraph_options
106
+ unless @options.empty?
107
+ parsed_options = []
108
+ @options.each do |option, value|
109
+ parsed_options << parse_paragraph_option(option, value)
110
+ end
111
+ Word::ParagraphProperties.new(parsed_options)
112
+ end
113
+ end
114
+
115
+ def parse_paragraph_option(option, value)
116
+ case option
117
+ when :alignment then Word::Alignment.new(value)
118
+ when :spacing then Word::Spacing.new(value)
119
+ when :indentation then Word::Indentation.new(value)
120
+ when :tabs then Word::Tabs.new(value)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -1,71 +1,121 @@
1
- module DocxGenerator
2
- module DSL
3
- class Text
4
- def initialize(text_fragment, options = {}, &block)
5
- @text_fragment = text_fragment
6
- @options = options
7
- yield self if block
8
- end
9
-
10
- def bold(value)
11
- @options[:bold] = value
12
- end
13
-
14
- def italics(value)
15
- @options[:italics] = value
16
- end
17
-
18
- def underline(value)
19
- @options[:underline] = value
20
- end
21
-
22
- def size(value)
23
- @options[:size] = value
24
- end
25
-
26
- def superscript(value)
27
- @options[:superscript] = value
28
- end
29
-
30
- def subscript(value)
31
- @options[:subscript] = value
32
- end
33
-
34
- def generate
35
- options = generate_text_options
36
- text = Word::Text.new({}, [@text_fragment])
37
- if options
38
- Word::Run.new({}, [options, text])
39
- else
40
- Word::Run.new({}, [text])
41
- end
42
- end
43
-
44
- def to_s
45
- generate.to_s
46
- end
47
-
48
- private
49
- def generate_text_options
50
- unless @options.empty?
51
- parsed_options = []
52
- @options.each do |option, value|
53
- parsed_options << parse_text_option(option, value)
54
- end
55
- Word::RunProperties.new(parsed_options)
56
- end
57
- end
58
-
59
- def parse_text_option(option, value)
60
- case option
61
- when :bold then Word::Bold.new(value)
62
- when :italics then Word::Italics.new(value)
63
- when :underline then Word::Underline.new(value)
64
- when :size then Word::Size.new(value)
65
- when :superscript then Word::VerticalAlign.new("superscript")
66
- when :subscript then Word::VerticalAlign.new("subscript")
67
- end
68
- end
69
- end
70
- end
71
- end
1
+ module DocxGenerator
2
+ module DSL
3
+ # Represent a text fragment with formatting options
4
+ class Text
5
+ # Create a new text fragment with the text specified.
6
+ # The formatting properties can be passed with a Hash or they could be set by calling the methods on the object (either in the block or not).
7
+ # @param text_fragment [String] The text fragment.
8
+ # @param options [Hash] Formatting options.
9
+ # @option options [Boolean] bold If the text should be in bold.
10
+ # @option options [Boolean] italics If the text should be in italics.
11
+ # @option options [Hash] underline The style of the underline and other options. See the specification for more details.
12
+ # @option options [Integer] size The size of the text (in points).
13
+ # @option options [Boolean] superscript If the text should be in superscript.
14
+ # @option options [Boolean] subscript If the text should be in subscript.
15
+ # @option options [Boolean] caps If the text should be displayed in capital letters.
16
+ # @option options [Boolean] small_caps If the text should be displayed in small capital letters.
17
+ # @option options [String] font The name of the font.
18
+ def initialize(text_fragment, options = {}, &block)
19
+ @text_fragment = text_fragment
20
+ @options = options
21
+ yield self if block
22
+ end
23
+
24
+ # Set whether the text should be in bold or not.
25
+ # @param value [Boolean] Whether the text should be in bold or not.
26
+ def bold(value)
27
+ @options[:bold] = value
28
+ end
29
+
30
+ # Set whether the text should be in italics or not.
31
+ # @param value [Boolean] Whether the text should be in italics or not.
32
+ def italics(value)
33
+ @options[:italics] = value
34
+ end
35
+
36
+ # Set the style of the underline and other options. See the specification for more details.
37
+ # @param value [Hash] The style of the underline and other options. See the specification for more details.
38
+ def underline(value)
39
+ @options[:underline] = value
40
+ end
41
+
42
+ # Set the size of the text (in points).
43
+ # @param value [Integer] The size of the text (in points).
44
+ def size(value)
45
+ @options[:size] = value
46
+ end
47
+
48
+ # Set whether the text should be in superscript.
49
+ # @param value [Boolean] Whether the text should be in superscript.
50
+ def superscript(value)
51
+ @options[:superscript] = value
52
+ end
53
+
54
+ # Set whether the text should be in subscript.
55
+ # @param value [Boolean] Whether the text should be in subscript.
56
+ def subscript(value)
57
+ @options[:subscript] = value
58
+ end
59
+
60
+ # Set whether the text should be displayed in capital letters.
61
+ # @param value [Boolean] Whether the text should be displayed in capital letters.
62
+ def caps(value)
63
+ @options[:caps] = value
64
+ end
65
+
66
+ # Set whether the text should be displayed in small capital letters.
67
+ # @param value [Boolean] Whether the text should be displayed in small capital letters.
68
+ def small_caps(value)
69
+ @options[:small_caps] = value
70
+ end
71
+
72
+ # Set the name of the font.
73
+ # @param value [String] The name of the font
74
+ def font(value)
75
+ @options[:font] = value
76
+ end
77
+
78
+ # Generate the XML element objects.
79
+ # @return [DocxGenerator::Word::Run] A Word::Run object representing the text fragment.
80
+ def generate
81
+ options = generate_text_options
82
+ text = Word::Text.new({}, [@text_fragment])
83
+ if options
84
+ Word::Run.new({}, [options, text])
85
+ else
86
+ Word::Run.new({}, [text])
87
+ end
88
+ end
89
+
90
+ # Generate the XML representation of the text fragment
91
+ def to_s
92
+ generate.to_s
93
+ end
94
+
95
+ private
96
+ def generate_text_options
97
+ unless @options.empty?
98
+ parsed_options = []
99
+ @options.each do |option, value|
100
+ parsed_options << parse_text_option(option, value)
101
+ end
102
+ Word::RunProperties.new(parsed_options)
103
+ end
104
+ end
105
+
106
+ def parse_text_option(option, value)
107
+ case option
108
+ when :bold then Word::Bold.new(value)
109
+ when :italics then Word::Italics.new(value)
110
+ when :underline then Word::Underline.new(value)
111
+ when :size then Word::Size.new(value)
112
+ when :superscript then Word::VerticalAlign.new("superscript")
113
+ when :subscript then Word::VerticalAlign.new("subscript")
114
+ when :caps then Word::CapitalLetters.new(value)
115
+ when :small_caps then Word::SmallCapitalLetters.new(value)
116
+ when :font then Word::Font.new(value)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end