Html2Docx 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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/Html2Docx.gemspec +31 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +35 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/Html2Docx.rb +50 -0
  13. data/lib/Html2Docx/content_types.rb +51 -0
  14. data/lib/Html2Docx/document.rb +95 -0
  15. data/lib/Html2Docx/document_objects/paragraph.rb +167 -0
  16. data/lib/Html2Docx/helpers/document_helper.rb +25 -0
  17. data/lib/Html2Docx/helpers/nokogiri_helper.rb +11 -0
  18. data/lib/Html2Docx/helpers/zip_file_generator.rb +46 -0
  19. data/lib/Html2Docx/initialization.rb +63 -0
  20. data/lib/Html2Docx/relation.rb +49 -0
  21. data/lib/Html2Docx/version.rb +3 -0
  22. data/samples/EmptyPage.docx +0 -0
  23. data/samples/EmptyPage.docx_FILES/[Content_Types].xml +1 -0
  24. data/samples/EmptyPage.docx_FILES/_rels/.rels +1 -0
  25. data/samples/EmptyPage.docx_FILES/docProps/app.xml +1 -0
  26. data/samples/EmptyPage.docx_FILES/docProps/core.xml +1 -0
  27. data/samples/EmptyPage.docx_FILES/word/_rels/document2.xml.rels +1 -0
  28. data/samples/EmptyPage.docx_FILES/word/document2.xml +1 -0
  29. data/samples/EmptyPage.docx_FILES/word/fontTable.xml +1 -0
  30. data/samples/EmptyPage.docx_FILES/word/settings.xml +1 -0
  31. data/samples/EmptyPage.docx_FILES/word/styles.xml +1 -0
  32. data/samples/EmptyPage.docx_FILES/word/theme/theme1.xml +2 -0
  33. data/samples/EmptyPage.docx_FILES/word/webSettings.xml +2 -0
  34. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx +0 -0
  35. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/[Content_Types].xml +1 -0
  36. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/_rels/.rels +1 -0
  37. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/docProps/app.xml +1 -0
  38. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/docProps/core.xml +1 -0
  39. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/_rels/document2.xml.rels +1 -0
  40. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/document2.xml +1 -0
  41. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/fontTable.xml +1 -0
  42. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/settings.xml +1 -0
  43. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/styles.xml +1 -0
  44. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/theme/theme1.xml +2 -0
  45. data/samples/TwoParagraphWithStrongItalicUnderLineAndStroke.docx_FILES/word/webSettings.xml +2 -0
  46. data/skell/[Content_Types].xml +1 -0
  47. data/skell/_rels/.rels +1 -0
  48. data/skell/docProps/app.xml +1 -0
  49. data/skell/docProps/core.xml +1 -0
  50. data/skell/word/_rels/document2.xml.rels +1 -0
  51. data/skell/word/document2.xml +1 -0
  52. data/skell/word/fontTable.xml +1 -0
  53. data/skell/word/settings.xml +1 -0
  54. data/skell/word/styles.xml +1 -0
  55. data/skell/word/theme/theme1.xml +2 -0
  56. data/skell/word/webSettings.xml +2 -0
  57. metadata +182 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b6b7d8747abec797383c45c6f202dd355a33175
4
+ data.tar.gz: 272f679b46c90ab98d72373a7ffa4fe4a80143f1
5
+ SHA512:
6
+ metadata.gz: a90cba4e4e72c7bb99b2bdcb8c98d869bb6e7f114df445a8e168ff246bd775ba515b0023c89858bbbe58ae30e4320c7d93be2638fd31d34462b8c8015249af92
7
+ data.tar.gz: abddd1eb858db18a00057926098c4668079bb62b2b6cedfc30471c4797248656004c2738ddfc38d9a311461a64fb6b8284356c2450341960fefed425271329ee
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.15.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in Html2Docx.gemspec
4
+ gemspec
data/Html2Docx.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'Html2Docx/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'Html2Docx'
8
+ spec.version = Html2Docx::VERSION
9
+ spec.authors = ['MuhammetDilmac']
10
+ spec.email = ['iletisim@muhammetdilmac.com.tr']
11
+
12
+ spec.summary = 'HTML çıktısından Docx oluşturmayı sağlayan ruby' \
13
+ 'kütüphanesi'
14
+ spec.description = 'Kendisine özel olarak oluşturulan html çıktısını ' \
15
+ 'işleyerek bu çıktıdan Docx üretmeyi sağlayan ruby ' \
16
+ 'kütüphanesi'
17
+ spec.homepage = 'https://www.github.com/MuhammetDilmac/Html2Docx'
18
+ spec.license = 'MIT'
19
+
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(test|spec|features)/})
22
+ end
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.15'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'nokogiri', '~> 1.6', '>= 1.6.8'
30
+ spec.add_development_dependency 'rubyzip', '~> 1.2', '>= 1.2.0'
31
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 MuhammetDilmac
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Html2Docx
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/Html2Docx`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'Html2Docx'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install Html2Docx
22
+
23
+ ## Usage
24
+
25
+ Html2Docx has very easy usage.
26
+
27
+ This time only supporting paragraph output. [Wiki - Paragraph Usage](https://github.com/MuhammetDilmac/Html2Docx/wiki/Paragraph-Usage)
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/MuhammetDilmac/Html2Docx. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
32
+
33
+ ## License
34
+
35
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "Html2Docx"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/Html2Docx.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'fileutils'
2
+ require 'nokogiri'
3
+ require 'zip'
4
+
5
+ require 'Html2Docx/helpers/document_helper'
6
+ require 'Html2Docx/helpers/nokogiri_helper'
7
+ require 'Html2Docx/helpers/zip_file_generator'
8
+
9
+ require 'Html2Docx/version'
10
+ require 'Html2Docx/initialization'
11
+ require 'Html2Docx/content_types'
12
+ require 'Html2Docx/relation'
13
+ require 'Html2Docx/document'
14
+ require 'Html2Docx/document_objects/paragraph'
15
+
16
+ module Html2Docx
17
+ ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '../'))
18
+
19
+ def self.clear_temp(tmp)
20
+ FileUtils.rm_r tmp
21
+ end
22
+
23
+ def self.create_docx(output, input)
24
+ zf = ZipFileGenerator.new(input, output)
25
+ zf.write
26
+
27
+ self.clear_temp(input)
28
+ end
29
+
30
+ def self.render(options = {})
31
+ initialization = Initialization.new(options)
32
+ options[:temp] = initialization.get_temp_directory
33
+
34
+ content_types = ContentTypes.new(options)
35
+
36
+ options[:main_relation] = true
37
+ relation = Relation.new(options)
38
+ options[:main_relation] = false
39
+
40
+ document = Document.new(options)
41
+
42
+ # Render
43
+ document.render
44
+ content_types.render
45
+ relation.render
46
+
47
+ # Create Docx File
48
+ self.create_docx(options.fetch(:output), options.fetch(:temp))
49
+ end
50
+ end
@@ -0,0 +1,51 @@
1
+ module Html2Docx
2
+ class ContentTypes
3
+ def initialize(options = {})
4
+ @content_type_file = File.join(options.fetch(:temp), '[Content_Types].xml')
5
+ @content_type = File.open(@content_type_file) {|f| Nokogiri::XML(f)}
6
+ @parts = {default: [], override: []}
7
+ initial_parts
8
+ end
9
+
10
+ def initial_parts
11
+ @content_type.root.children.each do |child|
12
+ if child.name == 'Default'
13
+ @parts[:default].push({extension: child.attr('Extension'), content_type: child.attr('ContentType')})
14
+ elsif child.name == 'Override'
15
+ @parts[:override].push({part_name: child.attr('PartName'), content_type: child.attr('ContentType')})
16
+ end
17
+
18
+ child.remove
19
+ end
20
+ end
21
+
22
+ def add_parts(object)
23
+ if object.fetch(:type) == 'Default'
24
+ @parts[:default].push({extension: object.fetch(:extension), content_type: object.fetch(:content_type)})
25
+ elsif object.fetch(:type) == 'Override'
26
+ @parts[:override].push({part_name: object.fetch(:part_name), content_type: object.fetch(:content_type)})
27
+ end
28
+ end
29
+
30
+ def render
31
+ @parts.fetch(:default).each { |child| add_default child}
32
+ @parts.fetch(:override).each { |child| add_override child}
33
+
34
+ File.open(@content_type_file, 'w') {|f| f.write Helpers::NokogiriHelper.to_xml(@content_type)}
35
+ end
36
+
37
+ def add_default(child)
38
+ node = Nokogiri::XML::Node.new('Default', @content_type)
39
+ node['Extension'] = child.fetch(:extension, '')
40
+ node['ContentType'] = child.fetch(:content_type, '')
41
+ @content_type.root << node
42
+ end
43
+
44
+ def add_override(child)
45
+ node = Nokogiri::XML::Node.new('Override', @content_type)
46
+ node['PartName'] = child.fetch(:part_name, '')
47
+ node['ContentType'] = child.fetch(:content_type, '')
48
+ @content_type.root << node
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,95 @@
1
+ module Html2Docx
2
+ class Document
3
+ def initialize(options = {})
4
+ @document_file = File.join(options.fetch(:temp), 'word', 'document2.xml')
5
+ @document = File.open(@document_file) { |f| Nokogiri::XML(f) }
6
+ @body = @document.at_xpath('//w:body')
7
+ @contents = []
8
+
9
+ initial_body
10
+ add_html(options[:html])
11
+ end
12
+
13
+ def initial_body
14
+ @body.children.each do |child|
15
+ child.remove
16
+ end
17
+ end
18
+
19
+ def add_html(html)
20
+ html = Nokogiri::HTML(html.gsub!(/\sl\s+|\n/, ' '))
21
+
22
+ elements = html.css('body')
23
+
24
+ elements.children.each do |element|
25
+ case element.name
26
+ when 'p'
27
+ # Add paragraph
28
+ paragraph = DocumentObjects::Paragraph.new(@document, nil)
29
+ paragraph.add_paragraph(element)
30
+ @contents.push paragraph.render
31
+ when 'table'
32
+ # Add table
33
+ @contents.push ''
34
+ end
35
+ end
36
+ end
37
+
38
+ def render
39
+ @contents.each do |content|
40
+ @body << content
41
+ end
42
+
43
+ @body << sectPr
44
+
45
+ @document.root.add_child(@body)
46
+
47
+ File.open(@document_file, 'w') { |f| f.write(Helpers::NokogiriHelper.to_xml(@document)) }
48
+ end
49
+
50
+ def sectPr
51
+ root = Nokogiri::XML::Node.new('w:sectPr', @document)
52
+ root.add_child(pgSz)
53
+ root.add_child(pgMar)
54
+ root.add_child(cols)
55
+ root.add_child(docGrid)
56
+
57
+ root
58
+ end
59
+
60
+ def pgSz
61
+ pgSz = Nokogiri::XML::Node.new('w:pgSz', @document)
62
+ pgSz['w:w'] = '12240'
63
+ pgSz['w:h'] = '15840'
64
+
65
+ pgSz
66
+ end
67
+
68
+ def pgMar
69
+ pgMar = Nokogiri::XML::Node.new('w:pgMar', @document)
70
+ pgMar['w:top'] = '1440'
71
+ pgMar['w:right'] = '1440'
72
+ pgMar['w:bottom'] = '1440'
73
+ pgMar['w:left'] = '1440'
74
+ pgMar['w:header'] = '720'
75
+ pgMar['w:footer'] = '720'
76
+ pgMar['w:gutter'] = '0'
77
+
78
+ pgMar
79
+ end
80
+
81
+ def cols
82
+ cols = Nokogiri::XML::Node.new('w:cols', @document)
83
+ cols['w:space'] = '720'
84
+
85
+ cols
86
+ end
87
+
88
+ def docGrid
89
+ docGrid = Nokogiri::XML::Node.new('w:docGrid', @document)
90
+ docGrid['w:linePitch'] = '360'
91
+
92
+ docGrid
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,167 @@
1
+ module Html2Docx
2
+ module DocumentObjects
3
+ class Paragraph
4
+ def initialize(document, relation)
5
+ @document = document
6
+ @relation = relation
7
+ @paragraph = nil
8
+ end
9
+
10
+ def add_paragraph(paragraph_object)
11
+ create_paragraph(paragraph_object)
12
+ end
13
+
14
+ def create_paragraph(paragraph_object)
15
+ @paragraph = Nokogiri::XML::Node.new('w:p', @document)
16
+
17
+ paragraph_style = paragraph_object.attr('style')
18
+ add_paragraph_style paragraph_style if paragraph_style
19
+
20
+ add_paragraph_child paragraph_object.children
21
+ end
22
+
23
+ def add_paragraph_style(style_attribute)
24
+ paragraph_style = Nokogiri::XML::Node.new('w:pPr', @document)
25
+ paragraph_styles = []
26
+
27
+ styles = style_attribute.split(';')
28
+
29
+ styles.each do |style|
30
+ style = style.strip
31
+ attribute, value = style.scan(/(.+):\s?(.+);?/).flatten
32
+
33
+ case attribute
34
+ when 'text-indent'
35
+ paragraph_styles.push add_paragraph_indent(value)
36
+ when 'text-align'
37
+ paragraph_styles.push add_paragraph_alignment(value)
38
+ when 'background-color'
39
+ paragraph_styles.push add_paragraph_background_color(value)
40
+ when 'line-height'
41
+ paragraph_styles.push add_line_height(value)
42
+ end
43
+ end
44
+
45
+ paragraph_styles.each do |style|
46
+ paragraph_style.add_child(style)
47
+ end
48
+
49
+ @paragraph.add_child(paragraph_style)
50
+ end
51
+
52
+ def add_paragraph_indent(value)
53
+ indent_tag = Nokogiri::XML::Node.new('w:ind', @document)
54
+ indent_tag['w:firstLine'] = Helpers::DocumentHelper.px_to_indent(value)
55
+
56
+ indent_tag
57
+ end
58
+
59
+ def add_paragraph_alignment(value)
60
+ align_tag = Nokogiri::XML::Node.new('w:jc', @document)
61
+ value = value.downcase
62
+ value = 'both' if value == 'justify'
63
+ align_tag['w:val'] = value
64
+
65
+ align_tag
66
+ end
67
+
68
+ def add_paragraph_background_color(value)
69
+ background_tag = Nokogiri::XML::Node.new('w:shd', @document)
70
+ background_tag['w:val'] = 'clear'
71
+ background_tag['w:color'] = 'auto'
72
+ background_tag['w:fill'] = Helpers::DocumentHelper.convert_hex_color(value)
73
+
74
+ background_tag
75
+ end
76
+
77
+ def add_line_height(value)
78
+ line_height_tag = Nokogiri::XML::Node.new('w:spacing', @document)
79
+ line_height_tag['w:line'] = Helpers::DocumentHelper.line_height(value)
80
+
81
+ line_height_tag
82
+ end
83
+
84
+ def add_paragraph_child(children)
85
+ children.each do |child|
86
+ text_field = create_text_field
87
+ text_style = create_text_style
88
+
89
+ case child.name
90
+ when 'strong'
91
+ text_field.add_child add_strong_text(text_style)
92
+ when 'i'
93
+ text_field.add_child add_italic_text(text_style)
94
+ when 'font'
95
+ color = child.attr('color')
96
+ text_field.add_child add_font_color(text_style, color) unless color.nil?
97
+ when 'u'
98
+ text_field.add_child add_underline_text(text_style)
99
+ when 's'
100
+ text_field.add_child add_stroke_text(text_style)
101
+ end
102
+
103
+ text_field.add_child add_paragraph_text(child.text)
104
+ @paragraph.add_child text_field
105
+ end
106
+ end
107
+
108
+ def create_text_field
109
+ Nokogiri::XML::Node.new('w:r', @document)
110
+ end
111
+
112
+ def create_text_style
113
+ Nokogiri::XML::Node.new('w:rPr', @document)
114
+ end
115
+
116
+ def add_paragraph_text(value)
117
+ plain_text = Nokogiri::XML::Node.new('w:t', @document)
118
+ plain_text['xml:space'] = 'preserve'
119
+ plain_text.content = value
120
+
121
+ plain_text
122
+ end
123
+
124
+ def add_strong_text(text_style)
125
+ strong_text = Nokogiri::XML::Node.new('w:b', @document)
126
+ text_style.add_child(strong_text)
127
+
128
+ text_style
129
+ end
130
+
131
+ def add_italic_text(text_style)
132
+ italic_text = Nokogiri::XML::Node.new('w:i', @document)
133
+ text_style.add_child(italic_text)
134
+
135
+ text_style
136
+ end
137
+
138
+ def add_font_color(text_style, color)
139
+ color_text = Nokogiri::XML::Node.new('w:color', @document)
140
+ color_text['w:val'] = Helpers::DocumentHelper.convert_hex_color(color)
141
+ text_style.add_child(color_text)
142
+
143
+ text_style
144
+ end
145
+
146
+ def add_underline_text(text_style)
147
+ underline_text = Nokogiri::XML::Node.new('w:u', @document)
148
+ underline_text['w:val'] = 'single'
149
+ text_style.add_child(underline_text)
150
+
151
+ text_style
152
+ end
153
+
154
+ def add_stroke_text(text_style)
155
+ stroke_text = Nokogiri::XML::Node.new('w:dstrike ', @document)
156
+ stroke_text['w:val'] = true
157
+ text_style.add_child(stroke_text)
158
+
159
+ text_style
160
+ end
161
+
162
+ def render
163
+ @paragraph
164
+ end
165
+ end
166
+ end
167
+ end