caracal 0.1.0

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +941 -0
  6. data/Rakefile +2 -0
  7. data/caracal.gemspec +27 -0
  8. data/lib/caracal.rb +31 -0
  9. data/lib/caracal/core/file_name.rb +39 -0
  10. data/lib/caracal/core/fonts.rb +75 -0
  11. data/lib/caracal/core/images.rb +37 -0
  12. data/lib/caracal/core/line_breaks.rb +29 -0
  13. data/lib/caracal/core/list_styles.rb +92 -0
  14. data/lib/caracal/core/lists.rb +57 -0
  15. data/lib/caracal/core/models/base_model.rb +51 -0
  16. data/lib/caracal/core/models/border_model.rb +120 -0
  17. data/lib/caracal/core/models/font_model.rb +64 -0
  18. data/lib/caracal/core/models/image_model.rb +118 -0
  19. data/lib/caracal/core/models/line_break_model.rb +15 -0
  20. data/lib/caracal/core/models/link_model.rb +65 -0
  21. data/lib/caracal/core/models/list_item_model.rb +105 -0
  22. data/lib/caracal/core/models/list_model.rb +130 -0
  23. data/lib/caracal/core/models/list_style_model.rb +129 -0
  24. data/lib/caracal/core/models/margin_model.rb +76 -0
  25. data/lib/caracal/core/models/page_break_model.rb +15 -0
  26. data/lib/caracal/core/models/page_number_model.rb +69 -0
  27. data/lib/caracal/core/models/page_size_model.rb +70 -0
  28. data/lib/caracal/core/models/paragraph_model.rb +141 -0
  29. data/lib/caracal/core/models/relationship_model.rb +108 -0
  30. data/lib/caracal/core/models/rule_model.rb +27 -0
  31. data/lib/caracal/core/models/style_model.rb +134 -0
  32. data/lib/caracal/core/models/table_cell_model.rb +155 -0
  33. data/lib/caracal/core/models/table_model.rb +206 -0
  34. data/lib/caracal/core/models/text_model.rb +92 -0
  35. data/lib/caracal/core/page_breaks.rb +29 -0
  36. data/lib/caracal/core/page_numbers.rb +51 -0
  37. data/lib/caracal/core/page_settings.rb +72 -0
  38. data/lib/caracal/core/relationships.rb +90 -0
  39. data/lib/caracal/core/rules.rb +35 -0
  40. data/lib/caracal/core/styles.rb +86 -0
  41. data/lib/caracal/core/tables.rb +41 -0
  42. data/lib/caracal/core/text.rb +73 -0
  43. data/lib/caracal/document.rb +242 -0
  44. data/lib/caracal/errors.rb +23 -0
  45. data/lib/caracal/renderers/app_renderer.rb +41 -0
  46. data/lib/caracal/renderers/content_types_renderer.rb +53 -0
  47. data/lib/caracal/renderers/core_renderer.rb +44 -0
  48. data/lib/caracal/renderers/document_renderer.rb +349 -0
  49. data/lib/caracal/renderers/fonts_renderer.rb +56 -0
  50. data/lib/caracal/renderers/footer_renderer.rb +69 -0
  51. data/lib/caracal/renderers/numbering_renderer.rb +87 -0
  52. data/lib/caracal/renderers/package_relationships_renderer.rb +50 -0
  53. data/lib/caracal/renderers/relationships_renderer.rb +48 -0
  54. data/lib/caracal/renderers/settings_renderer.rb +58 -0
  55. data/lib/caracal/renderers/styles_renderer.rb +163 -0
  56. data/lib/caracal/renderers/xml_renderer.rb +83 -0
  57. data/lib/caracal/version.rb +3 -0
  58. data/lib/tilt/caracal.rb +21 -0
  59. data/spec/lib/caracal/core/file_name_spec.rb +54 -0
  60. data/spec/lib/caracal/core/fonts_spec.rb +119 -0
  61. data/spec/lib/caracal/core/images_spec.rb +25 -0
  62. data/spec/lib/caracal/core/line_breaks_spec.rb +25 -0
  63. data/spec/lib/caracal/core/list_styles_spec.rb +121 -0
  64. data/spec/lib/caracal/core/lists_spec.rb +43 -0
  65. data/spec/lib/caracal/core/models/base_model_spec.rb +38 -0
  66. data/spec/lib/caracal/core/models/border_model_spec.rb +159 -0
  67. data/spec/lib/caracal/core/models/font_model_spec.rb +92 -0
  68. data/spec/lib/caracal/core/models/image_model_spec.rb +192 -0
  69. data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
  70. data/spec/lib/caracal/core/models/link_model_spec.rb +139 -0
  71. data/spec/lib/caracal/core/models/list_item_model_spec.rb +190 -0
  72. data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
  73. data/spec/lib/caracal/core/models/list_style_model_spec.rb +212 -0
  74. data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
  75. data/spec/lib/caracal/core/models/page_break_model_spec.rb +21 -0
  76. data/spec/lib/caracal/core/models/page_number_model_spec.rb +101 -0
  77. data/spec/lib/caracal/core/models/page_size_model_spec.rb +91 -0
  78. data/spec/lib/caracal/core/models/paragraph_model_spec.rb +162 -0
  79. data/spec/lib/caracal/core/models/relationship_model_spec.rb +183 -0
  80. data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
  81. data/spec/lib/caracal/core/models/style_model_spec.rb +187 -0
  82. data/spec/lib/caracal/core/models/table_cell_model_spec.rb +221 -0
  83. data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
  84. data/spec/lib/caracal/core/models/text_model_spec.rb +132 -0
  85. data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
  86. data/spec/lib/caracal/core/page_numbers_spec.rb +80 -0
  87. data/spec/lib/caracal/core/page_settings_spec.rb +143 -0
  88. data/spec/lib/caracal/core/relationships_spec.rb +119 -0
  89. data/spec/lib/caracal/core/rules_spec.rb +25 -0
  90. data/spec/lib/caracal/core/styles_spec.rb +129 -0
  91. data/spec/lib/caracal/core/tables_spec.rb +25 -0
  92. data/spec/lib/caracal/core/text_spec.rb +52 -0
  93. data/spec/lib/caracal/errors_spec.rb +10 -0
  94. data/spec/spec_helper.rb +8 -0
  95. metadata +245 -0
@@ -0,0 +1,83 @@
1
+ require 'nokogiri'
2
+
3
+
4
+ module Caracal
5
+ module Renderers
6
+ class XmlRenderer
7
+
8
+ #-------------------------------------------------------------
9
+ # Configuration
10
+ #-------------------------------------------------------------
11
+
12
+ attr_reader :document
13
+
14
+
15
+ #-------------------------------------------------------------
16
+ # Class Methods
17
+ #-------------------------------------------------------------
18
+
19
+ # This method produces xml output for the given document
20
+ # according to the rules of this renderer object.
21
+ #
22
+ def self.render(doc)
23
+ renderer = new(doc)
24
+ renderer.to_xml
25
+ end
26
+
27
+
28
+ #-------------------------------------------------------------
29
+ # Public Methods
30
+ #-------------------------------------------------------------
31
+
32
+ # This method instantiates a new verison of this renderer.
33
+ #
34
+ def initialize(doc)
35
+ unless doc.is_a?(Caracal::Document)
36
+ raise NoDocumentError, 'renderers must receive a reference to a valid Caracal document object.'
37
+ end
38
+
39
+ @document = doc
40
+ end
41
+
42
+ # This method converts data in the specified document to XML.
43
+ # A concrete implementation must be provided by the subclass.
44
+ #
45
+ def to_xml
46
+ raise NotImplementedError, 'renderers must implement the method :to_xml.'
47
+ end
48
+
49
+
50
+ #-------------------------------------------------------------
51
+ # Private Methods
52
+ #-------------------------------------------------------------
53
+ private
54
+
55
+ # This method returns a Nokogiri::XML object that contains the
56
+ # specific declaration we want.
57
+ #
58
+ def declaration_xml
59
+ ::Nokogiri::XML('<?xml version = "1.0" encoding = "UTF-8" standalone ="yes"?>')
60
+ end
61
+
62
+ # This method returns a commonly used set of attributes for paragraph nodes.
63
+ #
64
+ def paragraph_options
65
+ { 'w:rsidP' => '00000000', 'w:rsidRDefault' => '00000000' }.merge(run_options)
66
+ end
67
+
68
+ # This method returns a commonly used set of attributes for text run nodes.
69
+ #
70
+ def run_options
71
+ { 'w:rsidR' => '00000000', 'w:rsidRPr' => '00000000', 'w:rsidDel' => '00000000' }
72
+ end
73
+
74
+ # These save options force Nokogiri to remove indentation and
75
+ # line feeds from the output.
76
+ #
77
+ def save_options
78
+ { save_with: Nokogiri::XML::Node::SaveOptions::AS_XML }
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module Caracal
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'tilt/template'
2
+ require 'caracal'
3
+
4
+
5
+ module Tilt
6
+ class CaracalTemplate < Template
7
+ self.default_mime_type = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
8
+
9
+ def prepare
10
+ @code =<<-RUBY
11
+ Caracal::Document.render do |docx|
12
+ #{ data }
13
+ end
14
+ RUBY
15
+ end
16
+
17
+ def precompiled_template(locals)
18
+ @code
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caracal::Core::FileName do
4
+ let(:file_name) { 'test.docx' }
5
+
6
+ subject { Caracal::Document.new }
7
+
8
+
9
+ #-------------------------------------------------------------
10
+ # Configuration
11
+ #-------------------------------------------------------------
12
+
13
+ describe 'configuration tests' do
14
+
15
+ # constants
16
+ describe 'file name constants' do
17
+ it { expect(subject.class::DEFAULT_FILE_NAME).to eq 'caracal.docx' }
18
+ end
19
+
20
+ # accessors
21
+ describe 'file name readers' do
22
+ it { expect(subject.name).to eq 'caracal.docx' }
23
+ end
24
+
25
+ end
26
+
27
+
28
+ #-------------------------------------------------------------
29
+ # Public Methods
30
+ #-------------------------------------------------------------
31
+
32
+ describe 'public method tests' do
33
+
34
+ # .file_name
35
+ describe '.file_name' do
36
+ let(:new_name) { 'example.docx' }
37
+ let(:actual) { subject.name }
38
+
39
+ before { subject.file_name(new_name) }
40
+
41
+ describe 'when argument provided' do
42
+ it { expect(actual).to eq new_name }
43
+ end
44
+ describe 'when argument nil' do
45
+ let!(:previous) { subject.name }
46
+ let(:new_name) { nil }
47
+
48
+ it { expect(actual).to eq previous }
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caracal::Core::Fonts do
4
+ let(:f1) { Caracal::Core::Models::FontModel.new({ name: 'Helvetica' }) }
5
+ let(:f2) { Caracal::Core::Models::FontModel.new({ name: 'Garamond' }) }
6
+
7
+ subject { Caracal::Document.new }
8
+
9
+
10
+ #-------------------------------------------------------------
11
+ # Class Methods
12
+ #-------------------------------------------------------------
13
+
14
+ describe 'public class tests' do
15
+
16
+ # .default_fonts
17
+ describe '.default_fonts' do
18
+ let(:expected) { ['Arial', 'Trebuchet MS'] }
19
+ let(:actual) { subject.class.default_fonts.map { |r| r[:name] } }
20
+
21
+ it { expect(actual).to eq expected }
22
+ end
23
+
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Public Methods
29
+ #-------------------------------------------------------------
30
+
31
+ describe 'public method tests' do
32
+
33
+ #============== ATTRIBUTES =====================
34
+
35
+ # .font
36
+ describe '.font' do
37
+ it 'delegates font to registration method' do
38
+ expect(subject).to receive(:register_font)
39
+ subject.font({ name: 'Helvetica' })
40
+ end
41
+ end
42
+
43
+
44
+ #============== GETTERS ========================
45
+
46
+ # .fonts
47
+ describe '.fonts' do
48
+ it { expect(subject.fonts).to be_a(Array) }
49
+ end
50
+
51
+ # .find_font
52
+ describe '.find_font' do
53
+ let(:actual) { subject.find_font(key) }
54
+
55
+ before do
56
+ allow(subject).to receive(:fonts).and_return([f1])
57
+ end
58
+
59
+ describe 'when key is registered' do
60
+ let(:key) { f1.font_name }
61
+
62
+ it { expect(actual).to eq f1 }
63
+ end
64
+ describe 'when key is not registered' do
65
+ let(:key) { f2.font_name }
66
+
67
+ it { expect(actual).to eq nil }
68
+ end
69
+ end
70
+
71
+
72
+ #============== REGISTRATION ========================
73
+
74
+ # .register_font
75
+ describe '.register_font' do
76
+ let(:default_length) { subject.class.default_fonts.size }
77
+
78
+ describe 'when not already registered' do
79
+ before do
80
+ subject.register_font(f1)
81
+ end
82
+
83
+ it { expect(subject.fonts.size).to eq default_length + 1 }
84
+ end
85
+ describe 'when already registered' do
86
+ before do
87
+ subject.register_font(f1)
88
+ subject.register_font(f1)
89
+ end
90
+
91
+ it { expect(subject.fonts.size).to eq default_length + 1 }
92
+ end
93
+ end
94
+
95
+ # .unregister_font
96
+ describe '.unregister_font' do
97
+ let(:default_length) { subject.class.default_fonts.size }
98
+
99
+ describe 'when registered' do
100
+ before do
101
+ subject.register_font(f1)
102
+ subject.unregister_font(f1.font_name)
103
+ end
104
+
105
+ it { expect(subject.fonts.size).to eq default_length }
106
+ end
107
+ describe 'when not registered' do
108
+ before do
109
+ subject.register_font(f1)
110
+ subject.unregister_font(f2.font_name)
111
+ end
112
+
113
+ it { expect(subject.fonts.size).to eq default_length + 1 }
114
+ end
115
+ end
116
+
117
+ end
118
+
119
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caracal::Core::Images do
4
+ subject { Caracal::Document.new }
5
+
6
+
7
+ #-------------------------------------------------------------
8
+ # Public Methods
9
+ #-------------------------------------------------------------
10
+
11
+ describe 'public method tests' do
12
+
13
+ # .img
14
+ describe '.img' do
15
+ let!(:size) { subject.contents.size }
16
+
17
+ before { subject.img 'https://www.google.com/images/srpr/logo11w.png', width: 538, height: 190 }
18
+
19
+ it { expect(subject.contents.size).to eq size + 1 }
20
+ it { expect(subject.contents.last).to be_a(Caracal::Core::Models::ImageModel) }
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caracal::Core::LineBreaks do
4
+ subject { Caracal::Document.new }
5
+
6
+
7
+ #-------------------------------------------------------------
8
+ # Public Methods
9
+ #-------------------------------------------------------------
10
+
11
+ describe 'public method tests' do
12
+
13
+ # .br
14
+ describe '.br' do
15
+ let!(:size) { subject.contents.size }
16
+
17
+ before { subject.br }
18
+
19
+ it { expect(subject.contents.size).to eq size + 1 }
20
+ it { expect(subject.contents.last).to be_a(Caracal::Core::Models::LineBreakModel) }
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caracal::Core::ListStyles do
4
+ let(:s1) { Caracal::Core::Models::ListStyleModel.new({ type: :ordered, level: 10, format: 'decimal', value: '%1.' }) }
5
+ let(:s2) { Caracal::Core::Models::ListStyleModel.new({ type: :ordered, level: 11, format: 'lowerLetter', value: '%2.' }) }
6
+
7
+ subject { Caracal::Document.new }
8
+
9
+
10
+ #-------------------------------------------------------------
11
+ # Class Methods
12
+ #-------------------------------------------------------------
13
+
14
+ describe 'public class tests' do
15
+
16
+ # .default_list_styles
17
+ describe '.default_list_styles' do
18
+ let(:expected) { 18 }
19
+ let(:actual) { subject.class.default_list_styles.size }
20
+
21
+ it {expect(actual).to eq expected }
22
+ end
23
+
24
+ end
25
+
26
+
27
+ #-------------------------------------------------------------
28
+ # Public Methods
29
+ #-------------------------------------------------------------
30
+
31
+ describe 'public method tests' do
32
+
33
+ #============== ATTRIBUTES =====================
34
+
35
+ # .list_style
36
+ describe '.list_style' do
37
+ it 'delegates to registration method' do
38
+ expect(subject).to receive(:register_list_style)
39
+ subject.list_style({ type: :ordered, level: 2, format: 'decimal', value: '2f.' })
40
+ end
41
+ end
42
+
43
+
44
+ #============== GETTERS ========================
45
+
46
+ # .list_styles
47
+ describe '.list_styles' do
48
+ it { expect(subject.list_styles).to be_a(Array) }
49
+ end
50
+
51
+ # .find_list_style
52
+ describe '.find_list_style' do
53
+ let(:actual) { subject.find_list_style(type, level) }
54
+
55
+ before do
56
+ allow(subject).to receive(:list_styles).and_return([s1])
57
+ end
58
+
59
+ describe 'when key is registered' do
60
+ let(:type) { s1.style_type }
61
+ let(:level) { s1.style_level }
62
+
63
+ it { expect(actual).to eq s1 }
64
+ end
65
+ describe 'when key is not registered' do
66
+ let(:type) { s2.style_type }
67
+ let(:level) { s2.style_level }
68
+
69
+ it { expect(actual).to eq nil }
70
+ end
71
+ end
72
+
73
+
74
+ #============== REGISTRATION ========================
75
+
76
+ # .register_list_style
77
+ describe '.register_list_style' do
78
+ let(:default_length) { subject.class.default_list_styles.size }
79
+
80
+ describe 'when not already registered' do
81
+ before do
82
+ subject.register_list_style(s1)
83
+ end
84
+
85
+ it { expect(subject.list_styles.size).to eq default_length + 1 }
86
+ end
87
+ describe 'when already registered' do
88
+ before do
89
+ subject.register_list_style(s1)
90
+ subject.register_list_style(s1)
91
+ end
92
+
93
+ it { expect(subject.list_styles.size).to eq default_length + 1 }
94
+ end
95
+ end
96
+
97
+ # .unregister_list_style
98
+ describe '.unregister_list_style' do
99
+ let(:default_length) { subject.class.default_list_styles.size }
100
+
101
+ describe 'when registered' do
102
+ before do
103
+ subject.register_list_style(s1)
104
+ subject.unregister_list_style(s1.style_type, s1.style_level)
105
+ end
106
+
107
+ it { expect(subject.list_styles.size).to eq default_length }
108
+ end
109
+ describe 'when not registered' do
110
+ before do
111
+ subject.register_list_style(s1)
112
+ subject.unregister_list_style(s2.style_type, s2.style_level)
113
+ end
114
+
115
+ it { expect(subject.list_styles.size).to eq default_length + 1 }
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ end