htmltoword 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,7 +14,7 @@ Or install it yourself as:
14
14
 
15
15
  $ gem install htmltoword
16
16
 
17
- ## Usage
17
+ ## Usage
18
18
 
19
19
  ### Standalone
20
20
 
@@ -47,7 +47,7 @@ All standard html elements are supported and will create the closest equivalent
47
47
 
48
48
  ### Highlighting text
49
49
 
50
- You can add highlighting to text by wrapping it in a span with class h and adding a data style with a color that wordml supports (TODO: Provide list) ie:
50
+ You can add highlighting to text by wrapping it in a span with class h and adding a data style with a color that wordml supports (http://www.schemacentral.com/sc/ooxml/t-w_ST_HighlightColor.html) ie:
51
51
 
52
52
  ```html
53
53
  <span class="h" data-style="green">This text will have a green highlight</span>
@@ -70,7 +70,7 @@ The basic functioning of this gem can be summarised as:
70
70
  1. Transform inputed html to wordml.
71
71
  2. Unzip empty word docx file bundled with gem and replace its document.xml content with the new transformed result of step 1.
72
72
  3. Zip up contents again into a resulting .docx file.
73
-
73
+
74
74
  For more info about WordML: http://rep.oio.dk/microsoft.com/officeschemas/wordprocessingml_article.htm
75
75
 
76
76
  Contributions would be very much appreciated.
@@ -1,84 +1,19 @@
1
1
  # encoding: UTF-8
2
- require "htmltoword/version"
3
- require "htmltoword/htmltoword_helper"
4
2
  require "action_controller"
5
3
  require "action_view"
6
4
  require "nokogiri"
7
- require "zip/zip"
5
+ require "zip"
8
6
 
9
7
  module Htmltoword
10
8
  def self.root
11
9
  File.expand_path '../..', __FILE__
12
10
  end
11
+
13
12
  def self.templates_path
14
13
  File.join root, "templates"
15
14
  end
16
-
17
- class Document
18
-
19
- DOC_XML_FILE = "word/document.xml"
20
- BASIC_PATH = ::Htmltoword.root
21
- FILE_EXTENSION = ".docx"
22
- XSLT_TEMPLATE = File.join(BASIC_PATH, 'xslt', 'html_to_wordml.xslt')
23
-
24
- class << self
25
- include HtmltowordHelper
26
-
27
- def create content, file_name
28
- word_file = new(template_file, file_name)
29
- word_file.replace_file content
30
- word_file.save
31
- end
32
-
33
- def create_with_content template, file_name, content, set=nil
34
- word_file = new(template_file("#{template}#{FILE_EXTENSION}"), file_name)
35
- content = replace_values(content, set) if set
36
- word_file.replace_file content
37
- word_file.save
38
- end
39
- end
40
-
41
- def initialize(template_path, file_name)
42
- @file_name = file_name
43
- @replaceable_files = {}
44
- @template_zip = Zip::ZipFile.open(template_path)
45
- end
46
-
47
- def file_name
48
- @file_name
49
- end
50
-
51
- #
52
- # It creates missing folders if needed, creates a new zip/word file on the
53
- # specified location, copies all the files from the template word document
54
- # and replace the content of the ones to be replaced.
55
- # It will create a tempfile and return it. The rails app using the gem
56
- # should decide what to do with it.
57
- #
58
- #
59
- def save
60
- output_file = Tempfile.new([file_name, FILE_EXTENSION], type: 'application/zip')
61
- Zip::ZipOutputStream.open(output_file.path) do |out|
62
- @template_zip.each do |entry|
63
- out.put_next_entry entry.name
64
- if @replaceable_files[entry.name]
65
- out.write(@replaceable_files[entry.name])
66
- else
67
- out.write(@template_zip.read(entry.name))
68
- end
69
- end
70
- end
71
- @template_zip.close
72
- output_file.close
73
- return output_file
74
- end
75
-
76
- def replace_file html, file_name=DOC_XML_FILE
77
- source = Nokogiri::HTML(html.gsub(/>\s+</, "><"))
78
- xslt = Nokogiri::XSLT( File.read(XSLT_TEMPLATE) )
79
- source = xslt.transform( source ) unless (source/"/html").blank?
80
- @replaceable_files[file_name] = source.to_s
81
- end
82
-
83
- end
84
15
  end
16
+
17
+ require "htmltoword/version"
18
+ require "htmltoword/htmltoword_helper"
19
+ require "htmltoword/document"
@@ -0,0 +1,70 @@
1
+ module Htmltoword
2
+ class Document
3
+
4
+ DOC_XML_FILE = "word/document.xml"
5
+ BASIC_PATH = ::Htmltoword.root
6
+ FILE_EXTENSION = ".docx"
7
+ XSLT_TEMPLATE = File.join(BASIC_PATH, 'xslt', 'html_to_wordml.xslt')
8
+
9
+ class << self
10
+ include HtmltowordHelper
11
+
12
+ def create content, file_name
13
+ word_file = new(template_file, file_name)
14
+ word_file.replace_file content
15
+ word_file.save
16
+ end
17
+
18
+ def create_with_content template, file_name, content, set=nil
19
+ word_file = new(template_file("#{template}#{FILE_EXTENSION}"), file_name)
20
+ content = replace_values(content, set) if set
21
+ word_file.replace_file content
22
+ word_file.save
23
+ end
24
+ end
25
+
26
+ def initialize(template_path, file_name)
27
+ @file_name = file_name
28
+ @replaceable_files = {}
29
+ @template_path = template_path
30
+ end
31
+
32
+ def file_name
33
+ @file_name
34
+ end
35
+
36
+ #
37
+ # It creates missing folders if needed, creates a new zip/word file on the
38
+ # specified location, copies all the files from the template word document
39
+ # and replace the content of the ones to be replaced.
40
+ # It will create a tempfile and return it. The rails app using the gem
41
+ # should decide what to do with it.
42
+ #
43
+ #
44
+ def save
45
+ Tempfile.open([file_name, FILE_EXTENSION], type: 'application/zip') do |output_file|
46
+ Zip::File.open(@template_path) do |template_zip|
47
+ Zip::OutputStream.open(output_file.path) do |out|
48
+ template_zip.each do |entry|
49
+ out.put_next_entry entry.name
50
+ if @replaceable_files[entry.name]
51
+ out.write(@replaceable_files[entry.name])
52
+ else
53
+ out.write(template_zip.read(entry.name))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ output_file
59
+ end
60
+ end
61
+
62
+ def replace_file html, file_name=DOC_XML_FILE
63
+ source = Nokogiri::HTML(html.gsub(/>\s+</, "><"))
64
+ xslt = Nokogiri::XSLT( File.read(XSLT_TEMPLATE) )
65
+ source = xslt.transform( source ) unless (source/"/html").blank?
66
+ @replaceable_files[file_name] = source.to_s
67
+ end
68
+
69
+ end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Htmltoword
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -17,17 +17,17 @@
17
17
 
18
18
  <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="no" indent="yes" />
19
19
 
20
- <xsl:template match="/ | html">
20
+ <xsl:template match="/">
21
21
  <w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14">
22
- <xsl:apply-templates select="//body"/>
22
+ <xsl:apply-templates />
23
23
  </w:document>
24
24
  </xsl:template>
25
25
 
26
+ <xsl:template match="head" />
27
+
26
28
  <xsl:template match="body">
27
29
  <w:body>
28
- <w:p>
29
- <xsl:apply-templates/>
30
- </w:p>
30
+ <xsl:apply-templates/>
31
31
  <w:sectPr>
32
32
  <w:pgSz w:w="11906" w:h="16838"/>
33
33
  <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
@@ -37,83 +37,61 @@
37
37
  </w:body>
38
38
  </xsl:template>
39
39
 
40
- <xsl:template match="br">
41
- <xsl:choose>
42
- <xsl:when test="name(..)='div' or name(..)='small'">
43
- <w:r><w:br/></w:r>
44
- </xsl:when>
45
- <xsl:when test="name(..)='td'">
46
- </xsl:when>
47
- <xsl:otherwise>
48
- <w:pPr><w:pStyle w:val="Afsnit"/></w:pPr><w:r><w:br/></w:r>
49
- </xsl:otherwise>
50
- </xsl:choose>
51
- </xsl:template>
52
-
53
- <xsl:template match="i|em">
54
- <w:r>
55
- <w:rPr>
56
- <w:i />
57
- </w:rPr>
58
- <xsl:apply-templates />
59
- </w:r>
60
- </xsl:template>
61
-
62
- <xsl:template match="b|strong">
63
- <w:r>
64
- <w:rPr>
65
- <w:b />
66
- </w:rPr>
40
+ <xsl:template match="div[not(ancestor::p) and not(descendant::div) and not(descendant::p) and not(descendant::h1) and not(descendant::h2) and not(descendant::h3) and not(descendant::h4) and not(descendant::table)]">
41
+ <xsl:comment>Divs should create a p if nothing above them has and nothing below them will</xsl:comment>
42
+ <w:p>
67
43
  <xsl:apply-templates />
68
- </w:r>
69
- </xsl:template>
70
-
71
- <xsl:template match="font">
72
- <w:r>
73
- <xsl:apply-templates />
74
- </w:r>
75
- </xsl:template>
76
-
77
- <xsl:template match="div[@class='crumbNav']"/>
78
- <xsl:template match="small"/>
79
-
80
- <xsl:template match="div[contains(concat(' ', @class, ' '), ' -page-break ')]">
81
- <xsl:comment>Making PAGEBREAKS</xsl:comment>
82
- <w:r><w:br w:type="page" /></w:r>
83
- <xsl:apply-templates select="node()"/>
44
+ </w:p>
84
45
  </xsl:template>
85
46
 
86
47
  <xsl:template match="div">
87
- <xsl:choose>
88
- <xsl:when test="name(..)='body'">
89
- <xsl:apply-templates select="node()"/>
90
- </xsl:when>
91
- <xsl:when test="./div">
92
- <xsl:apply-templates select="node()"/>
93
- </xsl:when>
94
- <xsl:otherwise>
95
- <w:r><w:br/></w:r>
96
- <xsl:apply-templates select="node()"/>
97
- <w:r><w:br/></w:r>
98
- </xsl:otherwise>
99
- </xsl:choose>
48
+ <xsl:apply-templates />
100
49
  </xsl:template>
101
50
 
102
- <xsl:template match="p">
103
- <xsl:apply-templates/>
51
+ <xsl:template match="h1|h2|h3|h4|h5|h6">
52
+ <w:p>
53
+ <w:r>
54
+ <w:rPr>
55
+ <w:rStyle w:val="{name(.)}"/>
56
+ </w:rPr>
57
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
58
+ </w:r>
59
+ </w:p>
104
60
  </xsl:template>
105
61
 
106
- <xsl:template match="ol|ul">
107
- <w:r><w:br/></w:r>
108
- <xsl:apply-templates/>
109
- <w:r><w:br/></w:r>
62
+ <xsl:template match="p">
63
+ <w:p>
64
+ <w:r>
65
+ <xsl:apply-templates />
66
+ </w:r>
67
+ </w:p>
110
68
  </xsl:template>
111
69
 
112
70
  <xsl:template match="li">
113
- <w:r><w:t xml:space="preserve"> </w:t></w:r>
114
- <xsl:apply-templates/>
115
-
116
- <w:r><w:br/></w:r>
71
+ <w:p>
72
+ <w:r>
73
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
74
+ </w:r>
75
+ </w:p>
76
+ </xsl:template>
77
+
78
+ <xsl:template match="span[preceding-sibling::h1 or preceding-sibling::h2 or preceding-sibling::h3 or preceding-sibling::h4 or preceding-sibling::h5 or preceding-sibling::h6 or preceding-sibling::table]
79
+ |a[preceding-sibling::h1 or preceding-sibling::h2 or preceding-sibling::h3 or preceding-sibling::h4 or preceding-sibling::h5 or preceding-sibling::h6 or preceding-sibling::table]
80
+ |small[preceding-sibling::h1 or preceding-sibling::h2 or preceding-sibling::h3 or preceding-sibling::h4 or preceding-sibling::h5 or preceding-sibling::h6 or preceding-sibling::table]">
81
+ <xsl:comment>
82
+ In the following situation:
83
+
84
+ div
85
+ h2
86
+ span
87
+ textnode
88
+ p
89
+
90
+ The div template will not create a w:p because the div contains a h2. Therefore we need to wrap the span|a|small in a p here.
91
+ </xsl:comment>
92
+ <w:p>
93
+ <xsl:apply-templates />
94
+ </w:p>
117
95
  </xsl:template>
118
96
 
119
97
  <xsl:template match="span[contains(concat(' ', @class, ' '), ' h ')]">
@@ -121,6 +99,7 @@
121
99
  <xsl:choose>
122
100
  <xsl:when test="./@data-style='pink'">magenta</xsl:when>
123
101
  <xsl:when test="./@data-style='blue'">cyan</xsl:when>
102
+ <xsl:when test="./@data-style='orange'">darkYellow</xsl:when>
124
103
  <xsl:otherwise><xsl:value-of select="./@data-style"/></xsl:otherwise>
125
104
  </xsl:choose>
126
105
  </xsl:variable>
@@ -132,8 +111,13 @@
132
111
  </w:r>
133
112
  </xsl:template>
134
113
 
135
- <xsl:template match="span">
136
- <xsl:apply-templates/>
114
+ <xsl:template match="div[contains(concat(' ', @class, ' '), ' -page-break ')]">
115
+ <w:p>
116
+ <w:r>
117
+ <w:br w:type="page" />
118
+ </w:r>
119
+ </w:p>
120
+ <xsl:apply-templates />
137
121
  </xsl:template>
138
122
 
139
123
  <xsl:template match="table">
@@ -155,74 +139,78 @@
155
139
  <w:gridCol w:w="2310"/>
156
140
  <w:gridCol w:w="2310"/>
157
141
  </w:tblGrid>
158
- <xsl:apply-templates select="tr"/>
142
+ <xsl:apply-templates />
159
143
  </w:tbl>
160
144
  </xsl:template>
161
145
 
146
+ <xsl:template match="tbody">
147
+ <xsl:apply-templates />
148
+ </xsl:template>
149
+
162
150
  <xsl:template match="tr">
163
151
  <w:tr>
164
- <xsl:apply-templates select="td"/>
152
+ <xsl:apply-templates />
165
153
  </w:tr>
166
154
  </xsl:template>
167
155
 
168
156
  <xsl:template match="td">
169
157
  <w:tc>
170
- <xsl:apply-templates/>
158
+ <w:p>
159
+ <w:r>
160
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
161
+ </w:r>
162
+ </w:p>
171
163
  </w:tc>
172
164
  </xsl:template>
173
165
 
174
- <xsl:template match="a">
175
- <xsl:apply-templates/>
176
- </xsl:template>
177
-
178
- <xsl:template match="h1|h2|h3|h4">
179
- <w:r>
180
- <w:rPr>
181
- <w:rStyle w:val="{name(.)}"/>
182
- </w:rPr>
183
- <w:br/>
184
- <xsl:apply-templates />
185
- <w:br/>
186
- </w:r>
187
- </xsl:template>
188
-
189
166
  <xsl:template match="text()">
190
- <xsl:choose>
191
- <xsl:when test="name(..)='i' or name(..)='em' or name(..)='b' or name(..)='strong' or name(..)='font' or ancestor::h3 or ancestor::h2 or ancestor::h1 or ancestor::h4">
192
- <xsl:if test="string-length(.) > 0">
193
- <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
194
- </xsl:if>
195
- </xsl:when>
196
- <xsl:when test="name(..)='a' or name(..)='div' or name(..)='span' or name(..)='li' or name(..)='td' or name(..)='p'">
197
- <xsl:if test="string-length(.) > 0">
167
+ <xsl:if test="string-length(.) > 0">
168
+ <xsl:choose>
169
+ <xsl:when test="parent::i or parent::em">
198
170
  <w:r>
171
+ <w:rPr>
172
+ <w:i />
173
+ </w:rPr>
199
174
  <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
200
175
  </w:r>
201
- </xsl:if>
202
- </xsl:when>
203
- <xsl:otherwise>
204
- <xsl:comment>What to do with text '<xsl:value-of select="."/>' in <xsl:value-of select="name(..)"/> element?</xsl:comment>
205
- </xsl:otherwise>
206
- </xsl:choose>
207
-
208
- </xsl:template>
209
- <!--Need to tokenize the value of the class and remove the useless ones.-->
210
- <xsl:template match="@class">
211
- <xsl:choose>
212
- <xsl:when test="name(..)='span'">
213
- <xsl:comment>Is this being used? 1</xsl:comment>
214
- <w:rPr>
215
- <w:rStyle w:val="{.}"/>
216
- </w:rPr>
217
- </xsl:when>
218
- <xsl:when test="name(..)='div'">
219
- <xsl:comment>Is this being used? 2</xsl:comment>
220
- <w:pPr>
221
- <w:pStyle w:val="{.}"/>
222
- </w:pPr>
223
- </xsl:when>
224
- </xsl:choose>
176
+ </xsl:when>
177
+ <xsl:when test="parent::b or parent::strong">
178
+ <w:r>
179
+ <w:rPr>
180
+ <w:b />
181
+ </w:rPr>
182
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
183
+ </w:r>
184
+ </xsl:when>
185
+ <xsl:when test="parent::div and (preceding-sibling::h1 or preceding-sibling::h2 or preceding-sibling::h3 or preceding-sibling::h4 or preceding-sibling::h5 or preceding-sibling::h6 or preceding-sibling::table)">
186
+ <xsl:comment>
187
+ In the following situation:
188
+
189
+ div
190
+ h2
191
+ textnode
192
+
193
+ The div template will not create a w:p because the div contains a h2. Therefore we need to wrap the textnode in a p here.
194
+ </xsl:comment>
195
+ <w:p>
196
+ <w:r>
197
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
198
+ </w:r>
199
+ </w:p>
200
+ </xsl:when>
201
+ <xsl:otherwise>
202
+ <w:r>
203
+ <xsl:comment>text() fallback</xsl:comment>
204
+ <w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
205
+ </w:r>
206
+ </xsl:otherwise>
207
+ </xsl:choose>
208
+ </xsl:if>
225
209
  </xsl:template>
226
210
 
227
- </xsl:stylesheet>
228
211
 
212
+ <xsl:template match="*">
213
+ <xsl:apply-templates/>
214
+ </xsl:template>
215
+
216
+ </xsl:stylesheet>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: htmltoword
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-22 00:00:00.000000000 Z
12
+ date: 2013-09-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -48,17 +48,17 @@ dependencies:
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: 1.0.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 1.0.0
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rspec
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -114,21 +114,15 @@ executables: []
114
114
  extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
- - .gitignore
118
- - .travis.yml
119
- - Gemfile
120
- - LICENSE.txt
121
- - README.md
122
- - Rakefile
123
- - htmltoword.gemspec
124
- - lib/htmltoword.rb
117
+ - lib/htmltoword/document.rb
125
118
  - lib/htmltoword/htmltoword_helper.rb
126
119
  - lib/htmltoword/version.rb
127
- - spec/spec_helper.rb
128
- - spec/xslt_spec.rb
120
+ - lib/htmltoword.rb
129
121
  - templates/default.docx
130
122
  - xslt/html_to_wordml.xslt
131
123
  - xslt/style2.xslt
124
+ - README.md
125
+ - Rakefile
132
126
  homepage: http://github.com/nickfrandsen/htmltoword
133
127
  licenses:
134
128
  - MIT
@@ -156,6 +150,4 @@ specification_version: 3
156
150
  summary: This simple gem allows you to create MS Word docx documents from simple html
157
151
  documents. This makes it easy to create dynamic reports and forms that can be downloaded
158
152
  by your users as simple MS Word docx files.
159
- test_files:
160
- - spec/spec_helper.rb
161
- - spec/xslt_spec.rb
153
+ test_files: []
data/.gitignore DELETED
@@ -1,18 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- .idea/*
@@ -1,2 +0,0 @@
1
- language: ruby
2
- rvm: "1.9.3"
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in htmltoword.gemspec
4
- gemspec
@@ -1,22 +0,0 @@
1
- Copyright (c) 2013 Nicholas Frandsen
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,27 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'htmltoword/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "htmltoword"
8
- spec.version = Htmltoword::VERSION
9
- spec.authors = ["Nicholas Frandsen"]
10
- spec.email = ["nick.rowe.frandsen@gmail.com"]
11
- spec.description = %q{Convert html to word docx document.}
12
- spec.summary = %q{This simple gem allows you to create MS Word docx documents from simple html documents. This makes it easy to create dynamic reports and forms that can be downloaded by your users as simple MS Word docx files.}
13
- spec.homepage = "http://github.com/nickfrandsen/htmltoword"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_dependency "actionpack"
22
- spec.add_dependency "nokogiri"
23
- spec.add_dependency "rubyzip"
24
- spec.add_development_dependency "rspec"
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "rake"
27
- end
@@ -1,3 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'htmltoword'
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "XSLT" do
4
-
5
- it "transforms an empty html doc into an empty docx doc" do
6
- html = '<html><head></head><body></body></html>'
7
- compare_resulting_wordml_with_expected(html, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<w:document xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mo=\"http://schemas.microsoft.com/office/mac/office/2008/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:mv=\"urn:schemas-microsoft-com:mac:vml\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:pkg=\"http://schemas.microsoft.com/office/2006/xmlPackage\" xmlns:str=\"http://exslt.org/common\" xmlns:fn=\"http://www.w3.org/2005/xpath-functions\" mc:Ignorable=\"w14 wp14\">\n <w:body>\n <w:p/> <w:sectPr>\n <w:pgSz w:w=\"11906\" w:h=\"16838\"/>\n <w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\" w:header=\"708\" w:footer=\"708\" w:gutter=\"0\"/>\n <w:cols w:space=\"708\"/>\n <w:docGrid w:linePitch=\"360\"/>\n </w:sectPr>\n </w:body>\n</w:document>\n")
8
- end
9
-
10
- it "transforms a div into a docx block element." do
11
- html = '<html><head></head><body><div>Hello</div></body></html>'
12
- compare_resulting_wordml_with_expected(html, "<w:p> <w:r> <w:t xml:space=\"preserve\">Hello</w:t> </w:r> </w:p>")
13
- end
14
-
15
- context "transform a span" do
16
-
17
- it "into a docx block elmenet if child of body." do
18
- html = '<html><head></head><body><span>Hello</span></body></html>'
19
- compare_resulting_wordml_with_expected(html, "<w:p> <w:r> <w:t xml:space=\"preserve\">Hello</w:t> </w:r> </w:p>")
20
- end
21
-
22
- it "into a docx inline element if not child of body." do
23
- html = '<html><head></head><body><div><span>Hello</span></div></body></html>'
24
- compare_resulting_wordml_with_expected(html, "<w:p> <w:r> <w:t xml:space=\"preserve\">Hello</w:t> </w:r> </w:p>")
25
- end
26
-
27
- end
28
-
29
- it "transforms a p into a docx block element." do
30
- html = '<html><head></head><body><p>Hello</p></body></html>'
31
- compare_resulting_wordml_with_expected(html, "<w:p> <w:r> <w:t xml:space=\"preserve\">Hello</w:t> </w:r> </w:p>")
32
- end
33
-
34
- protected
35
-
36
- def compare_resulting_wordml_with_expected(html, resulting_wordml)
37
- source = Nokogiri::HTML(html.gsub(/>\s+</, "><"))
38
- xslt = Nokogiri::XSLT( File.read(Htmltoword::Document::XSLT_TEMPLATE))
39
- result = xslt.transform(source)
40
- if compare_content_of_body?(resulting_wordml)
41
- result.at("//w:sectPr").remove
42
- result = result.at("//w:body/*")
43
- end
44
- result.to_s.gsub(/\s+/, " ").should == resulting_wordml.gsub(/\s+/, " ")
45
- end
46
-
47
- def compare_content_of_body?(wordml)
48
- wordml !~ /<?xml version/
49
- end
50
-
51
- end