odf 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +76 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/lib/odf.rb +65 -0
  12. data/lib/odf/component/abstract.rb +23 -0
  13. data/lib/odf/component/content.rb +35 -0
  14. data/lib/odf/component/image_set.rb +42 -0
  15. data/lib/odf/component/manifest.rb +33 -0
  16. data/lib/odf/component/meta.rb +25 -0
  17. data/lib/odf/component/mime_type.rb +11 -0
  18. data/lib/odf/component/settings.rb +15 -0
  19. data/lib/odf/component/styles.rb +26 -0
  20. data/lib/odf/component/xml_component.rb +29 -0
  21. data/lib/odf/document/abstract.rb +67 -0
  22. data/lib/odf/document/presentation.rb +13 -0
  23. data/lib/odf/document/spreadsheet.rb +13 -0
  24. data/lib/odf/document/text.rb +17 -0
  25. data/lib/odf/element/abstract.rb +34 -0
  26. data/lib/odf/element/abstract_contenteable.rb +11 -0
  27. data/lib/odf/element/binary_data.rb +13 -0
  28. data/lib/odf/element/draw_frame.rb +50 -0
  29. data/lib/odf/element/draw_page.rb +15 -0
  30. data/lib/odf/element/draw_text_box.rb +38 -0
  31. data/lib/odf/element/heading.rb +18 -0
  32. data/lib/odf/element/image.rb +41 -0
  33. data/lib/odf/element/number.rb +14 -0
  34. data/lib/odf/element/paragraph.rb +14 -0
  35. data/lib/odf/element/table.rb +19 -0
  36. data/lib/odf/element/table_cell.rb +30 -0
  37. data/lib/odf/element/table_row.rb +16 -0
  38. data/lib/odf/element/text_list.rb +21 -0
  39. data/lib/odf/element/text_list_item.rb +29 -0
  40. data/lib/odf/utils/file.rb +45 -0
  41. data/lib/odf/utils/xml.rb +13 -0
  42. data/lib/odf/version.rb +3 -0
  43. data/odf.gemspec +32 -0
  44. data/templates/default_style.xml +2 -0
  45. metadata +185 -0
@@ -0,0 +1,29 @@
1
+ module Odf::Component
2
+ module XmlComponent
3
+
4
+ def self.included(base)
5
+ base.class_eval { attr_reader :xml }
6
+ end
7
+
8
+ def initialize(document)
9
+ super
10
+ initialize_xml
11
+ end
12
+
13
+ def content
14
+ wrap_xml
15
+ xml.to_xml
16
+ end
17
+
18
+ private
19
+ def initialize_xml
20
+ @xml = Odf::Utils::Xml.new
21
+ xml.encoding = "UTF-8"
22
+ end
23
+
24
+ def wrap_xml
25
+ true
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ module Odf::Document
2
+ class Abstract
3
+
4
+ COMPONENTS = [:content, :manifest, :meta, :mime_type, :styles, :settings]
5
+
6
+ attr_reader *(COMPONENTS + [:image_set])
7
+ attr_writer :creator
8
+
9
+ alias :document :itself
10
+
11
+ def initialize
12
+ @content = Odf::Component::Content.new(self)
13
+ @image_set = Odf::Component::ImageSet.new(self)
14
+ @manifest = Odf::Component::Manifest.new(self)
15
+ @meta = Odf::Component::Meta.new(self)
16
+ @mime_type = Odf::Component::MimeType.new(self)
17
+ @settings = Odf::Component::Settings.new(self)
18
+ @styles = Odf::Component::Styles.new(self)
19
+ end
20
+
21
+ # Returns the mime type of document.
22
+ # All subclasses of this abstract class
23
+ # should define the +MIME_TYPE+ constant.
24
+ def media_type
25
+ self.class::MIME_TYPE
26
+ end
27
+
28
+ # Returns the file extension for
29
+ # open document format.
30
+ def extension
31
+ self.class::EXTENSION
32
+ end
33
+
34
+ def wrapper
35
+ self.class::WRAPPER
36
+ end
37
+
38
+ # Returns the components of the document.
39
+ def components
40
+ COMPONENTS
41
+ end
42
+
43
+ # Returns the creator information.
44
+ def creator
45
+ @creator || Odf.creator
46
+ end
47
+
48
+ # Serialize the document to given path.
49
+ def serialize(file_name)
50
+ Odf::Utils::File.serialize(file_name, self) && true
51
+ end
52
+
53
+ # Returns the output stream.
54
+ def to_blob
55
+ Odf::Utils::File.output_stream(self)
56
+ end
57
+
58
+ def add_image(uri)
59
+ image_set << uri
60
+ end
61
+
62
+ def root
63
+ content.root
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ module Odf::Document
2
+ class Presentation < Abstract
3
+
4
+ MIME_TYPE = 'application/vnd.oasis.opendocument.presentation'.freeze
5
+ EXTENSION = 'odp'.freeze
6
+ WRAPPER = 'office:presentation'.freeze
7
+
8
+ def add_page(options = {})
9
+ Odf::Element::DrawPage.build(self, options)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Odf::Document
2
+ class Spreadsheet < Abstract
3
+
4
+ MIME_TYPE = 'application/vnd.oasis.opendocument.spreadsheet'.freeze
5
+ EXTENSION = 'ods'.freeze
6
+ WRAPPER = 'office:spreadsheet'.freeze
7
+
8
+ def add_table(options = {})
9
+ Odf::Element::Table.build(self, options)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Odf::Document
2
+ class Text < Abstract
3
+
4
+ MIME_TYPE = 'application/vnd.oasis.opendocument.text'.freeze
5
+ EXTENSION = 'odt'.freeze
6
+ WRAPPER = 'office:text'.freeze
7
+
8
+ def add_heading(text, options = {})
9
+ Odf::Element::Heading.build(self, text, options)
10
+ end
11
+
12
+ def add_paragraph(text, options = {})
13
+ Odf::Element::Paragraph.build(self, text, options)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ module Odf::Element
2
+ class Abstract
3
+
4
+ attr_reader :parent, :root
5
+
6
+ def initialize(parent, options = {})
7
+ @parent = parent
8
+ @root = document.content.xml.create_element(xml_tag, fetch_options(options))
9
+ @parent.root.add_child(@root)
10
+ end
11
+
12
+ # Accessor for valid options of element
13
+ def valid_options
14
+ @valid_options ||= defined?(self.class::VALID_OPTIONS) ? self.class::VALID_OPTIONS : {}
15
+ end
16
+
17
+ def xml_tag
18
+ self.class::XML_TAG
19
+ end
20
+
21
+ def document
22
+ parent.document
23
+ end
24
+
25
+ private
26
+ def fetch_options(options)
27
+ options.reduce({}) do |ret, (k, v)|
28
+ option = valid_options.fetch(k, k)
29
+ ret.merge(option => v)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ module Odf::Element
2
+ module AbstractContenteable
3
+
4
+ def initialize(parent, content, options = {})
5
+ @parent = parent
6
+ @root = document.content.xml.create_element(xml_tag, content, fetch_options(options))
7
+ @parent.root.add_child(@root)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Odf::Element
2
+ class BinaryData < Abstract
3
+
4
+ include AbstractContenteable
5
+
6
+ XML_TAG = 'office:binary-data'.freeze
7
+
8
+ def self.build(parent, content, options = {})
9
+ new(parent, content, options)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ module Odf::Element
2
+ class DrawFrame < Abstract
3
+
4
+ VALID_OPTIONS = {
5
+ caption_id: 'draw:caption-id',
6
+ class_names: 'draw:class-names',
7
+ copy_of: 'draw:copy-of',
8
+ id: 'draw:id',
9
+ name: 'draw:name',
10
+ style_name: 'draw:style-name',
11
+ text_style_name: 'draw:text-style-name',
12
+ transform: 'draw:transform',
13
+ z_index: 'draw:z-index',
14
+ p_class: 'presentation:class',
15
+ p_class_names: 'presentation:class-names',
16
+ placeholder: 'presentation:placeholder',
17
+ p_style_name: 'presentation:style-name',
18
+ user_transformed: 'presentation:user-transformed',
19
+ rel_height: 'style:rel-height',
20
+ rel_width: 'style:rel-width',
21
+ height: 'svg:height',
22
+ width: 'svg:width',
23
+ x: 'svg:x',
24
+ y: 'svg:y',
25
+ end_cell_address: 'table:end-cell-address',
26
+ end_x: 'table:end-x',
27
+ end_y: 'table:end-y',
28
+ table_background: 'table:table-background',
29
+ anchor_page_number: 'table:anchor-page-number',
30
+ anchor_type: 'table:anchor-type',
31
+ xml_id: 'xml:id',
32
+ layer: 'draw:layer'
33
+ }
34
+
35
+ XML_TAG = 'draw:frame'.freeze
36
+
37
+ def self.build(parent, options = {})
38
+ new(parent, options)
39
+ end
40
+
41
+ def add_text_box(options = {})
42
+ Odf::Element::DrawTextBox.build(self, options)
43
+ end
44
+
45
+ def add_image(options = {})
46
+ Odf::Element::Image.build(self, options)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,15 @@
1
+ module Odf::Element
2
+ class DrawPage < Abstract
3
+
4
+ XML_TAG = 'draw:page'.freeze
5
+
6
+ def self.build(document, options = {})
7
+ new(document, options)
8
+ end
9
+
10
+ def add_frame(options = {})
11
+ Odf::Element::DrawFrame.build(self, options)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module Odf::Element
2
+ class DrawTextBox < Abstract
3
+
4
+ VALID_OPTIONS = {
5
+ next_name: 'draw:chain-next-name',
6
+ corner_radius: 'draw:corner-radius',
7
+ max_height: 'fo:max-height',
8
+ max_width: 'fo:max-width',
9
+ min_height: 'fo:min-height',
10
+ min_width: 'fo:min-width',
11
+ text_id: 'text:id',
12
+ xml_id: 'xml:id'
13
+ }
14
+
15
+ XML_TAG = 'draw:text-box'.freeze
16
+
17
+ def self.build(parent, options = {})
18
+ new(parent, options)
19
+ end
20
+
21
+ def add_frame(options = {})
22
+ Odf::Element::DrawFrame.build(self, options)
23
+ end
24
+
25
+ def add_heading(text, options = {})
26
+ Odf::Element::Heading.build(self, text, options)
27
+ end
28
+
29
+ def add_paragraph(text, options = {})
30
+ Odf::Element::Paragraph.build(self, text, options)
31
+ end
32
+
33
+ def add_text_list(options = {})
34
+ Odf::Element::TextList.build(self, options)
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module Odf::Element
2
+ class Heading < Abstract
3
+
4
+ include AbstractContenteable
5
+
6
+ XML_TAG = 'text:h'.freeze
7
+
8
+ def self.build(parent, text, options = {})
9
+ new(parent, text, options)
10
+ end
11
+
12
+ def initialize(parent, content, options = {})
13
+ options = { level: 1 }.merge(options)
14
+ super(parent, content, options)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ module Odf::Element
2
+ class Image < Abstract
3
+
4
+ VALID_OPTIONS = {
5
+ filter_name: 'draw:filter-name',
6
+ actuate: 'xlink:actuate',
7
+ href: 'xlink:href',
8
+ show: 'xlink:show',
9
+ type: 'xlink:type',
10
+ xml_id: 'xml:id'
11
+ }
12
+
13
+ XML_TAG = 'draw:image'.freeze
14
+
15
+ def self.build(parent, options = {})
16
+ new(parent, options)
17
+ end
18
+
19
+ def initialize(parent, options)
20
+ @parent = parent
21
+
22
+ # Save image under Pictures directory
23
+ if options.fetch(:save, true) && options[:href]
24
+ uri = save_image(options[:href])
25
+ options.merge!({ href: uri, show: 'embed' })
26
+ end
27
+
28
+ super(parent, options)
29
+ end
30
+
31
+ def add_paragraph(text, options = {})
32
+ Odf::Element::Paragraph.build(self, text, options)
33
+ end
34
+
35
+ private
36
+ def save_image(href)
37
+ document.add_image(href)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ module Odf::Element
2
+ class Number < Abstract
3
+
4
+ include AbstractContenteable
5
+
6
+ VALID_OPTIONS = {}
7
+ XML_TAG = 'text:number'.freeze
8
+
9
+ def self.build(parent, text, options)
10
+ new(parent, text, options)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Odf::Element
2
+ class Paragraph < Abstract
3
+
4
+ include AbstractContenteable
5
+
6
+ VALID_OPTIONS = {}
7
+ XML_TAG = 'text:p'.freeze
8
+
9
+ def self.build(parent, text, options = {})
10
+ new(parent, text, options)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ module Odf::Element
2
+ class Table < Abstract
3
+
4
+ VALID_OPTIONS = {
5
+ table_name: 'table:name'
6
+ }
7
+
8
+ XML_TAG = 'table:table'.freeze
9
+
10
+ def self.build(parent, options = {})
11
+ new(parent, options)
12
+ end
13
+
14
+ def add_table_row(options = {})
15
+ Odf::Element::TableRow.build(self, options)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Odf::Element
2
+ class TableCell < Abstract
3
+
4
+ TYPE_MAP = {
5
+ Fixnum => 'float',
6
+ Float => 'float',
7
+ String => 'string'
8
+ }
9
+
10
+ VALID_OPTIONS = {}
11
+ XML_TAG = 'table:table-cell'.freeze
12
+
13
+ def self.build(parent, content, options = {})
14
+ type = options[:type] || infer_type(content)
15
+ self_opts = {
16
+ 'office:value-type' => type,
17
+ 'office:value' => content
18
+ }.merge(options)
19
+ this = new(parent, self_opts)
20
+
21
+ Odf::Element::Paragraph.build(this, content, options)
22
+ this
23
+ end
24
+
25
+ def self.infer_type(content)
26
+ TYPE_MAP[content.class] || 'string'
27
+ end
28
+
29
+ end
30
+ end