caracal_the_curve 1.4.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.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +22 -0
  3. data/.github/workflows/publish_gem.yml +40 -0
  4. data/.gitignore +25 -0
  5. data/.travis.yml +20 -0
  6. data/CHANGELOG.md +141 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +842 -0
  10. data/Rakefile +7 -0
  11. data/caracal.gemspec +28 -0
  12. data/lib/caracal/core/bookmarks.rb +52 -0
  13. data/lib/caracal/core/custom_properties.rb +49 -0
  14. data/lib/caracal/core/file_name.rb +43 -0
  15. data/lib/caracal/core/fonts.rb +75 -0
  16. data/lib/caracal/core/iframes.rb +42 -0
  17. data/lib/caracal/core/ignorables.rb +47 -0
  18. data/lib/caracal/core/images.rb +37 -0
  19. data/lib/caracal/core/list_styles.rb +93 -0
  20. data/lib/caracal/core/lists.rb +57 -0
  21. data/lib/caracal/core/models/base_model.rb +51 -0
  22. data/lib/caracal/core/models/bookmark_model.rb +86 -0
  23. data/lib/caracal/core/models/border_model.rb +120 -0
  24. data/lib/caracal/core/models/custom_property_model.rb +60 -0
  25. data/lib/caracal/core/models/font_model.rb +64 -0
  26. data/lib/caracal/core/models/iframe_model.rb +148 -0
  27. data/lib/caracal/core/models/image_model.rb +133 -0
  28. data/lib/caracal/core/models/line_break_model.rb +15 -0
  29. data/lib/caracal/core/models/link_model.rb +94 -0
  30. data/lib/caracal/core/models/list_item_model.rb +108 -0
  31. data/lib/caracal/core/models/list_model.rb +132 -0
  32. data/lib/caracal/core/models/list_style_model.rb +118 -0
  33. data/lib/caracal/core/models/margin_model.rb +76 -0
  34. data/lib/caracal/core/models/namespace_model.rb +65 -0
  35. data/lib/caracal/core/models/page_break_model.rb +61 -0
  36. data/lib/caracal/core/models/page_number_model.rb +95 -0
  37. data/lib/caracal/core/models/page_size_model.rb +79 -0
  38. data/lib/caracal/core/models/paragraph_model.rb +186 -0
  39. data/lib/caracal/core/models/relationship_model.rb +114 -0
  40. data/lib/caracal/core/models/rule_model.rb +27 -0
  41. data/lib/caracal/core/models/style_model.rb +165 -0
  42. data/lib/caracal/core/models/table_cell_model.rb +176 -0
  43. data/lib/caracal/core/models/table_model.rb +206 -0
  44. data/lib/caracal/core/models/text_model.rb +118 -0
  45. data/lib/caracal/core/namespaces.rb +89 -0
  46. data/lib/caracal/core/page_breaks.rb +29 -0
  47. data/lib/caracal/core/page_numbers.rb +58 -0
  48. data/lib/caracal/core/page_settings.rb +74 -0
  49. data/lib/caracal/core/relationships.rb +90 -0
  50. data/lib/caracal/core/rules.rb +35 -0
  51. data/lib/caracal/core/styles.rb +86 -0
  52. data/lib/caracal/core/tables.rb +42 -0
  53. data/lib/caracal/core/text.rb +75 -0
  54. data/lib/caracal/document.rb +272 -0
  55. data/lib/caracal/errors.rb +23 -0
  56. data/lib/caracal/renderers/app_renderer.rb +41 -0
  57. data/lib/caracal/renderers/content_types_renderer.rb +54 -0
  58. data/lib/caracal/renderers/core_renderer.rb +44 -0
  59. data/lib/caracal/renderers/custom_renderer.rb +64 -0
  60. data/lib/caracal/renderers/document_renderer.rb +427 -0
  61. data/lib/caracal/renderers/fonts_renderer.rb +56 -0
  62. data/lib/caracal/renderers/footer_renderer.rb +90 -0
  63. data/lib/caracal/renderers/numbering_renderer.rb +88 -0
  64. data/lib/caracal/renderers/package_relationships_renderer.rb +51 -0
  65. data/lib/caracal/renderers/relationships_renderer.rb +48 -0
  66. data/lib/caracal/renderers/settings_renderer.rb +58 -0
  67. data/lib/caracal/renderers/styles_renderer.rb +181 -0
  68. data/lib/caracal/renderers/xml_renderer.rb +83 -0
  69. data/lib/caracal/utilities.rb +23 -0
  70. data/lib/caracal/version.rb +3 -0
  71. data/lib/caracal.rb +40 -0
  72. data/lib/tilt/caracal.rb +21 -0
  73. data/spec/lib/caracal/core/bookmarks_spec.rb +35 -0
  74. data/spec/lib/caracal/core/file_name_spec.rb +54 -0
  75. data/spec/lib/caracal/core/fonts_spec.rb +119 -0
  76. data/spec/lib/caracal/core/iframes_spec.rb +29 -0
  77. data/spec/lib/caracal/core/ignorables_spec.rb +79 -0
  78. data/spec/lib/caracal/core/images_spec.rb +25 -0
  79. data/spec/lib/caracal/core/list_styles_spec.rb +121 -0
  80. data/spec/lib/caracal/core/lists_spec.rb +43 -0
  81. data/spec/lib/caracal/core/models/base_model_spec.rb +38 -0
  82. data/spec/lib/caracal/core/models/bookmark_model_spec.rb +135 -0
  83. data/spec/lib/caracal/core/models/border_model_spec.rb +159 -0
  84. data/spec/lib/caracal/core/models/font_model_spec.rb +92 -0
  85. data/spec/lib/caracal/core/models/iframe_model_spec.rb +83 -0
  86. data/spec/lib/caracal/core/models/image_model_spec.rb +225 -0
  87. data/spec/lib/caracal/core/models/line_break_model_spec.rb +21 -0
  88. data/spec/lib/caracal/core/models/link_model_spec.rb +179 -0
  89. data/spec/lib/caracal/core/models/list_item_model_spec.rb +197 -0
  90. data/spec/lib/caracal/core/models/list_model_spec.rb +178 -0
  91. data/spec/lib/caracal/core/models/list_style_model_spec.rb +198 -0
  92. data/spec/lib/caracal/core/models/margin_model_spec.rb +111 -0
  93. data/spec/lib/caracal/core/models/namespace_model_spec.rb +107 -0
  94. data/spec/lib/caracal/core/models/page_break_model_spec.rb +21 -0
  95. data/spec/lib/caracal/core/models/page_number_model_spec.rb +136 -0
  96. data/spec/lib/caracal/core/models/page_size_model_spec.rb +101 -0
  97. data/spec/lib/caracal/core/models/paragraph_model_spec.rb +196 -0
  98. data/spec/lib/caracal/core/models/relationship_model_spec.rb +193 -0
  99. data/spec/lib/caracal/core/models/rule_model_spec.rb +108 -0
  100. data/spec/lib/caracal/core/models/style_model_spec.rb +225 -0
  101. data/spec/lib/caracal/core/models/table_cell_model_spec.rb +230 -0
  102. data/spec/lib/caracal/core/models/table_model_spec.rb +222 -0
  103. data/spec/lib/caracal/core/models/text_model_spec.rb +154 -0
  104. data/spec/lib/caracal/core/namespaces_spec.rb +116 -0
  105. data/spec/lib/caracal/core/page_breaks_spec.rb +25 -0
  106. data/spec/lib/caracal/core/page_numbers_spec.rb +89 -0
  107. data/spec/lib/caracal/core/page_settings_spec.rb +151 -0
  108. data/spec/lib/caracal/core/relationships_spec.rb +119 -0
  109. data/spec/lib/caracal/core/rules_spec.rb +25 -0
  110. data/spec/lib/caracal/core/styles_spec.rb +129 -0
  111. data/spec/lib/caracal/core/tables_spec.rb +25 -0
  112. data/spec/lib/caracal/core/text_spec.rb +52 -0
  113. data/spec/lib/caracal/errors_spec.rb +10 -0
  114. data/spec/spec_helper.rb +8 -0
  115. data/spec/support/_fixtures/snippet.docx +0 -0
  116. metadata +292 -0
@@ -0,0 +1,56 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class FontsRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `word/fontTable.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml['w'].fonts root_options do
20
+ document.fonts.each do |font|
21
+ xml['w'].font({ 'w:name' => font.font_name })
22
+ end
23
+ end
24
+ end
25
+ builder.to_xml(save_options)
26
+ end
27
+
28
+
29
+ #-------------------------------------------------------------
30
+ # Private Methods
31
+ #-------------------------------------------------------------
32
+ private
33
+
34
+ def root_options
35
+ {
36
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
37
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
38
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
39
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
40
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
41
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
42
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
43
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
44
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
45
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
46
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
47
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
48
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
49
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
50
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
51
+ }
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,90 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class FooterRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `word/settings.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml['w'].ftr root_options do
20
+ xml['w'].p paragraph_options do
21
+ xml['w'].pPr do
22
+ xml['w'].contextualSpacing({ 'w:val' => '0' })
23
+ xml['w'].jc({ 'w:val' => "#{ document.page_number_align }" })
24
+ end
25
+ unless document.page_number_label.nil?
26
+ xml['w'].r run_options do
27
+ xml['w'].rPr do
28
+ xml['w'].rStyle({ 'w:val' => 'PageNumber' })
29
+ unless document.page_number_label_size.nil?
30
+ xml['w'].sz({ 'w:val' => document.page_number_label_size })
31
+ end
32
+ end
33
+ xml['w'].t({ 'xml:space' => 'preserve' }) do
34
+ xml.text "#{ document.page_number_label } "
35
+ end
36
+ end
37
+ end
38
+ xml['w'].r run_options do
39
+ xml['w'].rPr do
40
+ unless document.page_number_number_size.nil?
41
+ xml['w'].sz({ 'w:val' => document.page_number_number_size })
42
+ xml['w'].szCs({ 'w:val' => document.page_number_number_size })
43
+ end
44
+ end
45
+ xml['w'].fldChar({ 'w:fldCharType' => 'begin' })
46
+ xml['w'].instrText({ 'xml:space' => 'preserve' }) do
47
+ xml.text 'PAGE'
48
+ end
49
+ xml['w'].fldChar({ 'w:fldCharType' => 'end' })
50
+ end
51
+ xml['w'].r run_options do
52
+ xml['w'].rPr do
53
+ xml['w'].rtl({ 'w:val' => '0' })
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ builder.to_xml(save_options)
60
+ end
61
+
62
+
63
+ #-------------------------------------------------------------
64
+ # Private Methods
65
+ #-------------------------------------------------------------
66
+ private
67
+
68
+ def root_options
69
+ {
70
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
71
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
72
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
73
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
74
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
75
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
76
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
77
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
78
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
79
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
80
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
81
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
82
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
83
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
84
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
85
+ }
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,88 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/core/models/list_style_model'
4
+ require 'caracal/core/models/list_model'
5
+ require 'caracal/renderers/xml_renderer'
6
+
7
+
8
+ module Caracal
9
+ module Renderers
10
+ class NumberingRenderer < XmlRenderer
11
+
12
+ #-------------------------------------------------------------
13
+ # Public Methods
14
+ #-------------------------------------------------------------
15
+
16
+ # This method produces the xml required for the `word/numbering.xml`
17
+ # sub-document.
18
+ #
19
+ def to_xml
20
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
21
+ xml['w'].numbering root_options do
22
+
23
+ # add abstract definitions
24
+ document.toplevel_lists.each_with_index do |model, i|
25
+ xml['w'].abstractNum({ 'w:abstractNumId' => i + 1 }) do
26
+ xml['w'].multiLevelType({ 'w:val' => 'hybridMultilevel' })
27
+ model.level_map.each do |(level, type)|
28
+ if s = document.find_list_style(type, level)
29
+ xml['w'].lvl({ 'w:ilvl' => s.style_level }) do
30
+ xml['w'].start({ 'w:val' => s.style_start })
31
+ xml['w'].numFmt({ 'w:val' => s.style_format })
32
+ xml['w'].lvlRestart({ 'w:val' => s.style_restart })
33
+ xml['w'].lvlText({ 'w:val' => s.style_value })
34
+ xml['w'].lvlJc({ 'w:val' => s.style_align })
35
+ xml['w'].pPr do
36
+ xml['w'].ind({ 'w:left' => s.style_left, 'w:firstLine' => s.style_indent })
37
+ end
38
+ xml['w'].rPr do
39
+ xml['w'].u({ 'w:val' => 'none' })
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ # bind individual tables to abstract definitions
48
+ document.toplevel_lists.each_with_index do |model, i|
49
+ xml['w'].num({ 'w:numId' => i + 1 }) do
50
+ xml['w'].abstractNumId({ 'w:val' => i + 1 })
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+ builder.to_xml(save_options)
57
+ end
58
+
59
+
60
+
61
+ #-------------------------------------------------------------
62
+ # Private Methods
63
+ #-------------------------------------------------------------
64
+ private
65
+
66
+ def root_options
67
+ {
68
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
69
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
70
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
71
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
72
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
73
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
74
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
75
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
76
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
77
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
78
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
79
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
80
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
81
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
82
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
83
+ }
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,51 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class PackageRelationshipsRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `word/settings.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml.send 'Relationships', root_options do
20
+ relationship_data.each_with_index do |rel, index|
21
+ xml.send 'Relationship', { 'Target' => rel.first, 'Type' => rel.last, 'Id' => "rId#{ index + 1 }" }
22
+ end
23
+ end
24
+ end
25
+ builder.to_xml(save_options)
26
+ end
27
+
28
+
29
+ #-------------------------------------------------------------
30
+ # Private Methods
31
+ #-------------------------------------------------------------
32
+ private
33
+
34
+ def relationship_data
35
+ [
36
+ ['docProps/app.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'],
37
+ ['docProps/core.xml', 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties'],
38
+ ['docProps/custom.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties'],
39
+ ['word/document.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument']
40
+ ]
41
+ end
42
+
43
+ def root_options
44
+ {
45
+ 'xmlns' => 'http://schemas.openxmlformats.org/package/2006/relationships'
46
+ }
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class RelationshipsRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `word/settings.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml.send 'Relationships', root_options do
20
+ document.relationships.each do |rel|
21
+ xml.send 'Relationship', rel_options(rel)
22
+ end
23
+ end
24
+ end
25
+ builder.to_xml(save_options)
26
+ end
27
+
28
+
29
+ #-------------------------------------------------------------
30
+ # Private Methods
31
+ #-------------------------------------------------------------
32
+ private
33
+
34
+ def rel_options(rel)
35
+ opts = { 'Target' => rel.formatted_target, 'Type' => rel.formatted_type, 'Id' => rel.formatted_id}
36
+ opts['TargetMode'] = 'External' if rel.target_mode?
37
+ opts
38
+ end
39
+
40
+ def root_options
41
+ {
42
+ 'xmlns' => 'http://schemas.openxmlformats.org/package/2006/relationships'
43
+ }
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,58 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+
5
+
6
+ module Caracal
7
+ module Renderers
8
+ class SettingsRenderer < XmlRenderer
9
+
10
+ #-------------------------------------------------------------
11
+ # Public Methods
12
+ #-------------------------------------------------------------
13
+
14
+ # This method produces the xml required for the `word/settings.xml`
15
+ # sub-document.
16
+ #
17
+ def to_xml
18
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
19
+ xml['w'].settings root_options do
20
+ xml['w'].displayBackgroundShape({ 'w:val' => '1' })
21
+ xml['w'].defaultTabStop({ 'w:val' => '720' })
22
+ xml['w'].compat do
23
+ xml['w'].compatSetting({ 'w:val' => '14', 'w:name' => 'compatibilityMode', 'w:uri' => 'http://schemas.microsoft.com/office/word' })
24
+ end
25
+ end
26
+ end
27
+ builder.to_xml(save_options)
28
+ end
29
+
30
+
31
+ #-------------------------------------------------------------
32
+ # Private Methods
33
+ #-------------------------------------------------------------
34
+ private
35
+
36
+ def root_options
37
+ {
38
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
39
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
40
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
41
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
42
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
43
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
44
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
45
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
46
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
47
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
48
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
49
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
50
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
51
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
52
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
53
+ }
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,181 @@
1
+ require 'nokogiri'
2
+
3
+ require 'caracal/renderers/xml_renderer'
4
+ require 'caracal/errors'
5
+
6
+
7
+ module Caracal
8
+ module Renderers
9
+ class StylesRenderer < XmlRenderer
10
+
11
+ #----------------------------------------------------
12
+ # Public Methods
13
+ #----------------------------------------------------
14
+
15
+ # This method produces the xml required for the `word/styles.xml`
16
+ # sub-document.
17
+ #
18
+ def to_xml
19
+ builder = ::Nokogiri::XML::Builder.with(declaration_xml) do |xml|
20
+ xml['w'].styles root_options do
21
+
22
+ #========== DEFAULT STYLES ====================
23
+
24
+ unless s = document.default_style
25
+ raise Caracal::Errors::NoDefaultStyleError 'Document must declare a default paragraph style.'
26
+ end
27
+ xml['w'].docDefaults do
28
+ xml['w'].rPrDefault do
29
+ xml['w'].rPr do
30
+ xml['w'].rFonts font_options(s)
31
+ xml['w'].b({ 'w:val' => (s.style_bold ? '1' : '0') })
32
+ xml['w'].i({ 'w:val' => (s.style_italic ? '1' : '0') })
33
+ xml['w'].caps({ 'w:val' => (s.style_caps ? '1' : '0') })
34
+ xml['w'].smallCaps({ 'w:val' => '0' })
35
+ xml['w'].strike({ 'w:val' => '0' })
36
+ xml['w'].color({ 'w:val' => s.style_color })
37
+ xml['w'].sz({ 'w:val' => s.style_size })
38
+ xml['w'].u({ 'w:val' => (s.style_underline ? 'single' : 'none') })
39
+ xml['w'].vertAlign({ 'w:val' => 'baseline' })
40
+ end
41
+ end
42
+ xml['w'].pPrDefault do
43
+ xml['w'].pPr do
44
+ xml['w'].keepNext({ 'w:val' => '0' })
45
+ xml['w'].keepLines({ 'w:val' => '0' })
46
+ xml['w'].widowControl({ 'w:val' => '1' })
47
+ xml['w'].spacing(spacing_options(s, true))
48
+ xml['w'].ind(indentation_options(s, true))
49
+ xml['w'].jc({ 'w:val' => s.style_align.to_s })
50
+ end
51
+ end
52
+ end
53
+ xml['w'].style({ 'w:styleId' => s.style_id, 'w:type' => 'paragraph', 'w:default' => '1' }) do
54
+ xml['w'].name({ 'w:val' => s.style_name })
55
+ end
56
+ xml['w'].style({ 'w:styleId' => 'TableNormal', 'w:type' => 'table', 'w:default' => '1' }) do
57
+ xml['w'].name({ 'w:val' => 'Table Normal'})
58
+ xml['w'].pPr do
59
+ xml['w'].spacing({ 'w:lineRule' => 'auto', 'w:line' => (s.style_size * 20 * 1.15), 'w:before' => '0', 'w:after' => '0' })
60
+ end
61
+ end
62
+ default_id = s.style_id
63
+
64
+
65
+ #========== PARA/CHAR STYLES ==================
66
+
67
+ document.styles.reject { |s| s.style_id == default_id }.each do |s|
68
+ xml['w'].style({ 'w:styleId' => s.style_id, 'w:type' => s.style_type }) do
69
+ xml['w'].name({ 'w:val' => s.style_name })
70
+ xml['w'].basedOn({ 'w:val' => s.style_base })
71
+ xml['w'].next({ 'w:val' => s.style_next })
72
+ xml['w'].pPr do
73
+ xml['w'].keepNext({ 'w:val' => '0' })
74
+ xml['w'].keepLines({ 'w:val' => '0' })
75
+ xml['w'].widowControl({ 'w:val' => '1' })
76
+ xml['w'].spacing(spacing_options(s)) unless spacing_options(s).nil?
77
+ xml['w'].contextualSpacing({ 'w:val' => '1' })
78
+ xml['w'].jc({ 'w:val' => s.style_align.to_s }) unless s.style_align.nil?
79
+ xml['w'].ind(indentation_options(s)) unless indentation_options(s).nil?
80
+ end
81
+ xml['w'].rPr do
82
+ xml['w'].rFonts(font_options(s)) unless s.style_font.nil?
83
+ xml['w'].b({ 'w:val' => (s.style_bold ? '1' : '0') } ) unless s.style_bold.nil?
84
+ xml['w'].i({ 'w:val' => (s.style_italic ? '1' : '0') }) unless s.style_italic.nil?
85
+ xml['w'].caps({ 'w:val' => (s.style_caps ? '1' : '0') }) unless s.style_caps.nil?
86
+ xml['w'].color({ 'w:val' => s.style_color }) unless s.style_color.nil?
87
+ xml['w'].sz({ 'w:val' => s.style_size }) unless s.style_size.nil?
88
+ xml['w'].u({ 'w:val' => (s.style_underline ? 'single' : 'none') }) unless s.style_underline.nil?
89
+ end
90
+ end
91
+ end
92
+
93
+ #========== TABLE STYLES ======================
94
+
95
+ xml['w'].style({ 'w:styleId' => 'DefaultTable', 'w:type' => 'table' }) do
96
+ xml['w'].basedOn({ 'w:val' => 'TableNormal' })
97
+ xml['w'].tblPr do
98
+ xml['w'].tblStyleRowBandSize({ 'w:val' => '1' })
99
+ xml['w'].tblStyleColBandSize({ 'w:val' => '1' })
100
+ end
101
+ %w(band1Horz band1Vert band2Horz band2Vert).each do |type|
102
+ xml['w'].tblStylePr({ 'w:type' => type })
103
+ end
104
+ %w(firstCol firstRow lastCol lastRow).each do |type|
105
+ xml['w'].tblStylePr({ 'w:type' => type })
106
+ end
107
+ %w(neCell nwCell seCell swCell).each do |type|
108
+ xml['w'].tblStylePr({ 'w:type' => type })
109
+ end
110
+ end
111
+
112
+ end
113
+ end
114
+ builder.to_xml(save_options)
115
+ end
116
+
117
+
118
+
119
+ #----------------------------------------------------
120
+ # Private Methods
121
+ #----------------------------------------------------
122
+ private
123
+
124
+ def font_options(style)
125
+ name = style.style_font
126
+ { 'w:cs' => name, 'w:hAnsi' => name, 'w:eastAsia' => name, 'w:ascii' => name }
127
+ end
128
+
129
+ def indentation_options(style, default=false)
130
+ left = (default) ? style.style_indent_left.to_i : style.style_indent_left
131
+ right = (default) ? style.style_indent_right.to_i : style.style_indent_right
132
+ first = (default) ? style.style_indent_first.to_i : style.style_indent_first
133
+ options = nil
134
+ if [left, right, first].compact.size > 0
135
+ options = {}
136
+ options['w:left'] = left unless left.nil?
137
+ options['w:right'] = right unless right.nil?
138
+ options['w:firstLine'] = first unless first.nil?
139
+ end
140
+ options
141
+ end
142
+
143
+ def root_options
144
+ {
145
+ 'xmlns:mc' => 'http://schemas.openxmlformats.org/markup-compatibility/2006',
146
+ 'xmlns:o' => 'urn:schemas-microsoft-com:office:office',
147
+ 'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
148
+ 'xmlns:m' => 'http://schemas.openxmlformats.org/officeDocument/2006/math',
149
+ 'xmlns:v' => 'urn:schemas-microsoft-com:vml',
150
+ 'xmlns:wp' => 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
151
+ 'xmlns:w10' => 'urn:schemas-microsoft-com:office:word',
152
+ 'xmlns:w' => 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
153
+ 'xmlns:wne' => 'http://schemas.microsoft.com/office/word/2006/wordml',
154
+ 'xmlns:sl' => 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
155
+ 'xmlns:a' => 'http://schemas.openxmlformats.org/drawingml/2006/main',
156
+ 'xmlns:pic' => 'http://schemas.openxmlformats.org/drawingml/2006/picture',
157
+ 'xmlns:c' => 'http://schemas.openxmlformats.org/drawingml/2006/chart',
158
+ 'xmlns:lc' => 'http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas',
159
+ 'xmlns:dgm' => 'http://schemas.openxmlformats.org/drawingml/2006/diagram'
160
+ }
161
+ end
162
+
163
+ def spacing_options(style, default=false)
164
+ top = (default) ? style.style_top.to_i : style.style_top
165
+ bottom = (default) ? style.style_bottom.to_i : style.style_bottom
166
+ line = style.style_line
167
+
168
+ options = nil
169
+ if [top, bottom, line].compact.size > 0
170
+ options = {}
171
+ options['w:lineRule'] = 'auto'
172
+ options['w:before'] = top unless top.nil?
173
+ options['w:after'] = bottom unless bottom.nil?
174
+ options['w:line'] = line unless line.nil?
175
+ end
176
+ options
177
+ end
178
+
179
+ end
180
+ end
181
+ end
@@ -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