htmltoword 0.4.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: befba72eb576d39090834848e2d36f81a89eb55f
4
- data.tar.gz: c10496fa4f4a07f6a0ef22ded7f3fede7a5be334
3
+ metadata.gz: e6be38e580ebe86fd332a24f97b1c75a9f5f2ae7
4
+ data.tar.gz: e19adf814c82af95c2ed51ea67145c4b622173be
5
5
  SHA512:
6
- metadata.gz: d859816964b95338f9396118e02316406efaa921a50c522314ddb836af6b0ff29f15fa3eda2c46649bca055f3d6afcffaabf5281236cd7851fe2a424315b0f7f
7
- data.tar.gz: e7e58429b762efb32c24ab52fbcbe0148ab78f339c5d350d1feeef2154cfa5aa35526e4ecd1446ce15e7e05c9807b038b3496827ff58461a355e98d05afaca6a
6
+ metadata.gz: 0ab229591820f8846076f63bcf6dbe4eedac8f537247f8fe8d7dd7621862f9461f50d3687d0cc4ea0cb16fa1a6a04449fadb566c1df32cd65aa1aa9676004392
7
+ data.tar.gz: 03f99d75484650577e4328a059431eba8e15ca71063fd47d1e492b8a60dccdce44a8c00383b6135c1ea0335f19025b771efba56fb9b56e8f2e3723159355e777
@@ -36,10 +36,18 @@ module Htmltoword
36
36
  'word/numbering.xml'
37
37
  end
38
38
 
39
+ def relations_xml_file
40
+ 'word/_rels/document.xml.rels'
41
+ end
42
+
39
43
  def numbering_xslt
40
44
  File.join(Htmltoword.config.default_xslt_path, 'numbering.xslt')
41
45
  end
42
46
 
47
+ def relations_xslt
48
+ File.join(Htmltoword.config.default_xslt_path, 'relations.xslt')
49
+ end
50
+
43
51
  def xslt_template(extras = false)
44
52
  File.join(Htmltoword.config.default_xslt_path, (extras ? 'htmltoword.xslt' : 'base.xslt'))
45
53
  end
@@ -76,7 +84,9 @@ module Htmltoword
76
84
  html = html.presence || '<body></body>'
77
85
  source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
78
86
  transform_and_replace(source, Document.numbering_xslt, Document.numbering_xml_file)
79
- transform_and_replace(source, Document.xslt_template(extras), file_name, extras)
87
+ transform_and_replace(source, Document.relations_xslt, Document.relations_xml_file)
88
+ cleaned_source = Nokogiri::XSLT(File.open(File.join(Htmltoword.config.default_xslt_path, 'inline_elements.xslt'))).transform(source)
89
+ transform_and_replace(cleaned_source, Document.xslt_template(extras), file_name, extras)
80
90
  end
81
91
 
82
92
  private
@@ -1,3 +1,3 @@
1
1
  module Htmltoword
2
- VERSION = "0.4.4"
2
+ VERSION = "0.5"
3
3
  end
@@ -18,6 +18,7 @@
18
18
  <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
19
19
  <xsl:include href="./functions.xslt"/>
20
20
  <xsl:include href="./tables.xslt"/>
21
+ <xsl:include href="./links.xslt"/>
21
22
 
22
23
  <xsl:template match="/">
23
24
  <xsl:apply-templates />
@@ -50,14 +51,14 @@
50
51
  </xsl:template>
51
52
 
52
53
 
53
- <xsl:template match="br[not(ancestor::p) and not(ancestor::div) and not(name(..)='td') and not(name(..)='li') or
54
+ <xsl:template match="br[not(ancestor::p) and not(ancestor::div) and not(ancestor::td|ancestor::li) or
54
55
  (preceding-sibling::div or following-sibling::div or preceding-sibling::p or following-sibling::p)]">
55
56
  <w:p>
56
57
  <w:r></w:r>
57
58
  </w:p>
58
59
  </xsl:template>
59
60
 
60
- <xsl:template match="br[(name(..)='li' or name(..)='td') and
61
+ <xsl:template match="br[(ancestor::li or ancestor::td) and
61
62
  (preceding-sibling::div or following-sibling::div or preceding-sibling::p or following-sibling::p)]">
62
63
  <w:r>
63
64
  <w:br />
@@ -109,31 +110,72 @@
109
110
  </xsl:template>
110
111
 
111
112
  <xsl:template match="ol|ul">
112
- <xsl:param name="local_level" select="0"/>
113
113
  <xsl:param name="global_level" select="count(preceding::ol[not(ancestor::ol or ancestor::ul)]) + count(preceding::ul[not(ancestor::ol or ancestor::ul)]) + 1"/>
114
114
  <xsl:apply-templates>
115
- <xsl:with-param name="local_level" select="$local_level + 1" />
116
115
  <xsl:with-param name="global_level" select="$global_level" />
117
116
  </xsl:apply-templates>
118
117
  </xsl:template>
119
118
 
120
- <xsl:template match="li">
121
- <xsl:param name="local_level" />
119
+ <xsl:template name="listItem" match="li">
122
120
  <xsl:param name="global_level" />
123
- <w:p>
124
- <w:pPr>
125
- <w:pStyle w:val="ListParagraph"></w:pStyle>
126
- <w:numPr>
127
- <w:ilvl w:val="{$local_level - 1}"/>
128
- <w:numId w:val="{$global_level}"/>
129
- </w:numPr>
130
- </w:pPr>
131
- <xsl:apply-templates select="*[not(name()='ol' or name()='ul')]|text()"/>
132
- </w:p>
133
- <xsl:apply-templates select="./ol|./ul">
134
- <xsl:with-param name="local_level" select="$local_level" />
135
- <xsl:with-param name="global_level" select="$global_level" />
136
- </xsl:apply-templates>
121
+ <xsl:param name="preceding-siblings" select="0"/>
122
+ <xsl:for-each select="node()">
123
+ <xsl:choose>
124
+ <xsl:when test="self::br">
125
+ <w:p>
126
+ <w:pPr>
127
+ <w:pStyle w:val="ListParagraph"></w:pStyle>
128
+ <w:numPr>
129
+ <w:ilvl w:val="0"/>
130
+ <w:numId w:val="0"/>
131
+ </w:numPr>
132
+ </w:pPr>
133
+ <w:r></w:r>
134
+ </w:p>
135
+ </xsl:when>
136
+ <xsl:when test="self::ol|self::ul">
137
+ <xsl:apply-templates>
138
+ <xsl:with-param name="global_level" select="$global_level" />
139
+ </xsl:apply-templates>
140
+ </xsl:when>
141
+ <xsl:when test="not(descendant::li)"> <!-- simpler div, p, headings, etc... -->
142
+ <xsl:variable name="ilvl" select="count(ancestor::ol) + count(ancestor::ul) - 1"></xsl:variable>
143
+ <xsl:choose>
144
+ <xsl:when test="$preceding-siblings + count(preceding-sibling::*) > 0">
145
+ <w:p>
146
+ <w:pPr>
147
+ <w:pStyle w:val="ListParagraph"></w:pStyle>
148
+ <w:numPr>
149
+ <w:ilvl w:val="0"/>
150
+ <w:numId w:val="0"/>
151
+ </w:numPr>
152
+ <w:ind w:left="{720 * ($ilvl + 1)}"/>
153
+ </w:pPr>
154
+ <xsl:apply-templates/>
155
+ </w:p>
156
+ </xsl:when>
157
+ <xsl:otherwise>
158
+ <w:p>
159
+ <w:pPr>
160
+ <w:pStyle w:val="ListParagraph"></w:pStyle>
161
+ <w:numPr>
162
+ <w:ilvl w:val="{$ilvl}"/>
163
+ <w:numId w:val="{$global_level}"/>
164
+ </w:numPr>
165
+ </w:pPr>
166
+ <xsl:apply-templates/>
167
+ </w:p>
168
+ </xsl:otherwise>
169
+ </xsl:choose>
170
+ </xsl:when>
171
+ <xsl:otherwise> <!-- mixed things div having list and stuff content... -->
172
+ <xsl:call-template name="listItem">
173
+ <xsl:with-param name="global_level" select="$global_level" />
174
+ <xsl:with-param name="preceding-siblings" select="$preceding-siblings + count(preceding-sibling::*)" />
175
+ </xsl:call-template>
176
+ </xsl:otherwise>
177
+ </xsl:choose>
178
+ </xsl:for-each>
137
179
  </xsl:template>
138
180
 
139
181
  <xsl:template match="span[not(ancestor::td) and not(ancestor::li) 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 or preceding-sibling::p or preceding-sibling::ol or preceding-sibling::ul or preceding-sibling::div or following-sibling::h1 or following-sibling::h2 or following-sibling::h3 or following-sibling::h4 or following-sibling::h5 or following-sibling::h6 or following-sibling::table or following-sibling::p or following-sibling::ol or following-sibling::ul or following-sibling::div)]
@@ -158,7 +200,14 @@
158
200
  The div template will not create a w:p because the div contains a h2. Therefore we need to wrap the inline elements span|a|small in a p here.
159
201
  </xsl:comment>
160
202
  <w:p>
161
- <xsl:apply-templates />
203
+ <xsl:choose>
204
+ <xsl:when test="self::a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]">
205
+ <xsl:call-template name="link" />
206
+ </xsl:when>
207
+ <xsl:otherwise>
208
+ <xsl:apply-templates />
209
+ </xsl:otherwise>
210
+ </xsl:choose>
162
211
  </w:p>
163
212
  </xsl:template>
164
213
 
@@ -0,0 +1,39 @@
1
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
2
+ <xsl:output encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
3
+
4
+ <xsl:strip-space elements="*"/>
5
+
6
+ <xsl:template match="node()|@*">
7
+ <xsl:copy>
8
+ <xsl:apply-templates select="@*|node()[1]"/>
9
+ </xsl:copy>
10
+ <xsl:apply-templates select="following-sibling::node()[1]"/>
11
+ </xsl:template>
12
+
13
+ <!-- get first inline element of a sequence or text having block element siblings... -->
14
+ <xsl:template match="node()[self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()][parent::div|parent::li|parent::td]">
15
+ <div>
16
+ <xsl:attribute name="class"><xsl:value-of select="../@class"/></xsl:attribute>
17
+ <xsl:attribute name="style"><xsl:value-of select="../@style"/></xsl:attribute>
18
+ <xsl:call-template name="inlineElement"/>
19
+ </div>
20
+ <xsl:apply-templates select="following-sibling::node()[not((self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text())[parent::div|parent::li|parent::td])][1]"/>
21
+ </xsl:template>
22
+
23
+ <!-- get following inline elements... -->
24
+ <xsl:template match="a[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
25
+ |b[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
26
+ |em[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
27
+ |i[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
28
+ |small[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
29
+ |span[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
30
+ |strong[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
31
+ |u[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]
32
+ |text()[preceding-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]]"
33
+ name="inlineElement">
34
+ <xsl:copy>
35
+ <xsl:apply-templates select="@*|node()[1]"/>
36
+ </xsl:copy>
37
+ <xsl:apply-templates select="following-sibling::node()[1][self::a|self::b|self::em|self::i|self::small|self::span|self::strong|self::u|self::text()]"/>
38
+ </xsl:template>
39
+ </xsl:stylesheet>
@@ -0,0 +1,35 @@
1
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
2
+ xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
3
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
4
+ xmlns:o="urn:schemas-microsoft-com:office:office"
5
+ xmlns:v="urn:schemas-microsoft-com:vml"
6
+ xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
7
+ xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
8
+ xmlns:w10="urn:schemas-microsoft-com:office:word"
9
+ xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
10
+ xmlns:msxsl="urn:schemas-microsoft-com:xslt"
11
+ xmlns:ext="http://www.xmllab.net/wordml2html/ext"
12
+ xmlns:java="http://xml.apache.org/xalan/java"
13
+ xmlns:str="http://exslt.org/strings"
14
+ xmlns:func="http://exslt.org/functions"
15
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
16
+ version="1.0"
17
+ exclude-result-prefixes="java msxsl ext w o v WX aml w10"
18
+ extension-element-prefixes="func">
19
+
20
+ <xsl:template match="a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]" name="link">
21
+ <w:hyperlink>
22
+ <xsl:attribute name="r:id">rId<xsl:value-of select="count(preceding::a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]) + 8" /></xsl:attribute>
23
+ <w:r>
24
+ <w:rPr>
25
+ <w:rStyle w:val="Hyperlink"/>
26
+ <w:color w:val="000080"/>
27
+ <w:u w:val="single"/>
28
+ </w:rPr>
29
+ <w:t xml:space="preserve">
30
+ <xsl:value-of select="."/>
31
+ </w:t>
32
+ </w:r>
33
+ </w:hyperlink>
34
+ </xsl:template>
35
+ </xsl:stylesheet>
@@ -72,26 +72,22 @@
72
72
  </w:numbering>
73
73
  </xsl:template>
74
74
 
75
- <xsl:template match="ol|ul">
76
- <xsl:param name="local_level" select="0"/>
77
- <xsl:param name="global_level" select="count(preceding::ol[not(ancestor::ol or ancestor::ul)]) + count(preceding::ul[not(ancestor::ol or ancestor::ul)]) + 1"/>
75
+ <xsl:template name="container" match="ol|ul">
76
+ <xsl:variable name="global_level" select="count(preceding::ol[not(ancestor::ol or ancestor::ul)]) + count(preceding::ul[not(ancestor::ol or ancestor::ul)]) + 1"/>
78
77
  <xsl:variable name="style" select="func:list-type(name(.), concat(' ', @style, ' '), concat(' ', @class, ' '))"/>
79
78
  <xsl:choose>
80
- <xsl:when test="$local_level = 0">
79
+ <xsl:when test="not(ancestor::ol or ancestor::ul)">
81
80
  <w:abstractNum w:abstractNumId="{$global_level - 1}">
82
81
  <w:nsid w:val="{concat('099A08C', $global_level)}"/>
83
82
  <w:multiLevelType w:val="hybridMultilevel"/>
84
83
  <xsl:call-template name="numbering_level">
85
- <xsl:with-param name="ilvl" select="$local_level"/>
84
+ <xsl:with-param name="ilvl" select="0"/>
86
85
  <xsl:with-param name="style" select="$style"/>
87
86
  </xsl:call-template>
88
- <xsl:apply-templates>
89
- <xsl:with-param name="local_level" select="$local_level + 1" />
90
- <xsl:with-param name="global_level" select="$global_level" />
91
- </xsl:apply-templates>
92
- <xsl:if test="count(.//ol) + count(.//ul) = 0">
87
+ <xsl:call-template name="item"/>
88
+ <xsl:if test="count(.//ol|.//ul) &lt; 6">
93
89
  <xsl:call-template name="autocomplete">
94
- <xsl:with-param name="ilvl" select="$local_level + 1"/>
90
+ <xsl:with-param name="ilvl" select="count(.//ol) + count(.//ul)"/>
95
91
  <xsl:with-param name="style" select="$style"/>
96
92
  </xsl:call-template>
97
93
  </xsl:if>
@@ -99,31 +95,25 @@
99
95
  </xsl:when>
100
96
  <xsl:otherwise>
101
97
  <xsl:call-template name="numbering_level">
102
- <xsl:with-param name="ilvl" select="$local_level"/>
98
+ <xsl:with-param name="ilvl" select="count(ancestor::ol) + count(ancestor::ul)"/>
103
99
  <xsl:with-param name="style" select="$style"/>
104
100
  </xsl:call-template>
105
- <xsl:apply-templates>
106
- <xsl:with-param name="local_level" select="$local_level + 1" />
107
- <xsl:with-param name="global_level" select="$global_level" />
108
- </xsl:apply-templates>
109
-
110
- <xsl:if test="count(.//ol) + count(.//ul) = 0">
111
- <xsl:call-template name="autocomplete">
112
- <xsl:with-param name="ilvl" select="$local_level + 1"/>
113
- <xsl:with-param name="style" select="$style"/>
114
- </xsl:call-template>
115
- </xsl:if>
101
+ <xsl:call-template name="item"/>
116
102
  </xsl:otherwise>
117
103
  </xsl:choose>
118
104
  </xsl:template>
119
105
 
120
- <xsl:template match="li">
121
- <xsl:param name="local_level" />
122
- <xsl:param name="global_level" />
123
- <xsl:apply-templates select="./ol|./ul">
124
- <xsl:with-param name="local_level" select="$local_level" />
125
- <xsl:with-param name="global_level" select="$global_level" />
126
- </xsl:apply-templates>
106
+ <xsl:template name="item">
107
+ <xsl:for-each select="node()">
108
+ <xsl:choose>
109
+ <xsl:when test="self::ol|self::ul">
110
+ <xsl:call-template name="container"/>
111
+ </xsl:when>
112
+ <xsl:otherwise>
113
+ <xsl:call-template name="item"/>
114
+ </xsl:otherwise>
115
+ </xsl:choose>
116
+ </xsl:for-each>
127
117
  </xsl:template>
128
118
 
129
119
  <xsl:template match="*">
@@ -165,13 +155,19 @@
165
155
  <xsl:template name="autocomplete">
166
156
  <xsl:param name="ilvl"/>
167
157
  <xsl:param name="style" />
168
- <xsl:if test="$ilvl &lt; 6">
158
+ <xsl:variable name="current_level">
159
+ <xsl:choose>
160
+ <xsl:when test="$ilvl &lt; 1">1</xsl:when>
161
+ <xsl:otherwise><xsl:value-of select="$ilvl"/></xsl:otherwise>
162
+ </xsl:choose>
163
+ </xsl:variable>
164
+ <xsl:if test="$current_level &lt; 6">
169
165
  <xsl:call-template name="numbering_level">
170
- <xsl:with-param name="ilvl" select="$ilvl"/>
166
+ <xsl:with-param name="ilvl" select="$current_level"/>
171
167
  <xsl:with-param name="style" select="$style"/>
172
168
  </xsl:call-template>
173
169
  <xsl:call-template name="autocomplete">
174
- <xsl:with-param name="ilvl" select="$ilvl + 1"/>
170
+ <xsl:with-param name="ilvl" select="$current_level + 1"/>
175
171
  <xsl:with-param name="style" select="$style"/>
176
172
  </xsl:call-template>
177
173
  </xsl:if>
@@ -190,5 +186,4 @@
190
186
  </xsl:call-template>
191
187
  </xsl:if>
192
188
  </xsl:template>
193
-
194
189
  </xsl:stylesheet>
@@ -0,0 +1,26 @@
1
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
2
+ xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
3
+ version="1.0">
4
+ <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
5
+
6
+ <xsl:template match="a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]" priority="1">
7
+ <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="{@href}" TargetMode="External">
8
+ <xsl:attribute name="Id">rId<xsl:value-of select="count(preceding::a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]) + 8"/></xsl:attribute>
9
+ </Relationship>
10
+ </xsl:template>
11
+
12
+ <xsl:template match="/">
13
+ <Relationships>
14
+ <Relationship Id="rId3" Type="http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects" Target="stylesWithEffects.xml"/>
15
+ <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
16
+ <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
17
+ <Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
18
+ <Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
19
+ <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>
20
+ <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
21
+ <xsl:apply-templates select="*"/>
22
+ </Relationships>
23
+ </xsl:template>
24
+
25
+ <xsl:template match="text()|@*"/>
26
+ </xsl:stylesheet>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: htmltoword
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicholas Frandsen, Cristina Matonte
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-16 00:00:00.000000000 Z
11
+ date: 2015-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -144,7 +144,10 @@ files:
144
144
  - lib/htmltoword/xslt/extras.xslt
145
145
  - lib/htmltoword/xslt/functions.xslt
146
146
  - lib/htmltoword/xslt/htmltoword.xslt
147
+ - lib/htmltoword/xslt/inline_elements.xslt
148
+ - lib/htmltoword/xslt/links.xslt
147
149
  - lib/htmltoword/xslt/numbering.xslt
150
+ - lib/htmltoword/xslt/relations.xslt
148
151
  - lib/htmltoword/xslt/style2.xslt
149
152
  - lib/htmltoword/xslt/tables.xslt
150
153
  homepage: http://github.com/karnov/htmltoword