Showing preview only (400K chars total). Download the full file or copy to clipboard to get everything.
Repository: karnov/htmltoword
Branch: master
Commit: d58f91145356
Files: 75
Total size: 377.3 KB
Directory structure:
gitextract_jrowts2d/
├── .gitattributes
├── .gitignore
├── CHANGELOG.txt
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin/
│ └── htmltoword
├── docs/
│ ├── styles.md
│ └── supported_elements.md
├── htmltoword.gemspec
├── lib/
│ ├── htmltoword/
│ │ ├── configuration.rb
│ │ ├── document.rb
│ │ ├── helpers/
│ │ │ ├── templates_helper.rb
│ │ │ └── xslt_helper.rb
│ │ ├── railtie.rb
│ │ ├── renderer.rb
│ │ ├── templates/
│ │ │ └── default.docx
│ │ ├── version.rb
│ │ └── xslt/
│ │ ├── base.xslt
│ │ ├── cleanup.xslt
│ │ ├── extras.xslt
│ │ ├── functions.xslt
│ │ ├── htmltoword.xslt
│ │ ├── image_functions.xslt
│ │ ├── images.xslt
│ │ ├── inline_elements.xslt
│ │ ├── links.xslt
│ │ ├── numbering.xslt
│ │ ├── relations.xslt
│ │ ├── style2.xslt
│ │ └── tables.xslt
│ └── htmltoword.rb
├── script/
│ ├── build-template
│ ├── extract-template
│ └── setup
├── spec/
│ ├── document_spec.rb
│ ├── fixtures/
│ │ ├── complex/
│ │ │ ├── nestings.html
│ │ │ └── nestings.xml
│ │ ├── description_lists/
│ │ │ ├── test01.html
│ │ │ ├── test01.xml
│ │ │ ├── test02.html
│ │ │ ├── test02.xml
│ │ │ ├── test03.html
│ │ │ ├── test03.xml
│ │ │ ├── test04.html
│ │ │ └── test04.xml
│ │ └── lists/
│ │ ├── lists_inline_elements.html
│ │ └── lists_inline_elements.xml
│ ├── spec_helper.rb
│ ├── tmp/
│ │ └── .gitignore
│ ├── xslt_alignment_spec.rb
│ ├── xslt_breaks_spec.rb
│ ├── xslt_complex_spec.rb
│ ├── xslt_description_lists_spec.rb
│ ├── xslt_heading_spec.rb
│ ├── xslt_images_spec.rb
│ ├── xslt_links_spec.rb
│ ├── xslt_lists_spec.rb
│ ├── xslt_simple_text_style_spec.rb
│ ├── xslt_spec.rb
│ └── xslt_tables_spec.rb
└── templates/
└── default/
├── [Content_Types].xml
├── _rels/
│ └── .rels
├── docProps/
│ ├── app.xml
│ └── core.xml
└── word/
├── _rels/
│ └── document.xml.rels
├── document.xml
├── fontTable.xml
├── numbering.xml
├── settings.xml
├── styles.xml
├── stylesWithEffects.xml
├── theme/
│ └── theme1.xml
└── webSettings.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
templates/**/*.xml filter=xml-c14n
templates/**/*.rels filter=xml-c14n
================================================
FILE: .gitignore
================================================
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
spec/reports
test/tmp
test/version_tmp
.idea/*
================================================
FILE: CHANGELOG.txt
================================================
CHANGELOG
Version 0.6.0
* Improve support for inline elements
* Add basic support for section and article elements
Version 0.5.1
* Bugfix on ActionController::Renderers formats
Version 0.5
* Better handling of external links
* Better handling of inline elements
* Better support for complex lists
Version 0.4.4
* Update default template to remove language
* Bug fixes on lists and tables having br elements
* Bug fixes on lists having inline elements and div or p tags
* Bug fix on corrupted docx files generated in Windows
* Add basic support to 'pre' tag
Version 0.4.3
* Add method that generates and saves the document to a file in a specific file path
Version 0.4.2
* Fix broken default template
* List support
* Support table cells bordering in the base xslt
* br tag support
Version 0.4.1
* Include forgotten templates and xslt
Version 0.4
* Do not render output to file, but rather to a buffer.
This means that apps using the gem no longer needs write permissions on a filesystem.
* Support of table borders using the extra xslt
* Support of basic lists using the extra xslt
* Use of blockquotes as a replacement for spacing usint the extra xslt
* Add a command line interface
* Fixes on default template metadata
Version 0.2
* Relocation of templates and xslt files
* Enable gem configuration to set the location of default and custom word templates and xslt.
* Allow the Htmltoword::Document.create to receive custom templates
* Add .docx as a renderer when used with rails.
Version 0.1.8
* Better alignment of text within a paragraph, div or table cell if it has a 'center', 'left', 'right', 'justify' class or by using the text-align property.
* Support for table-bordered class on tables
* Support for bold and italic text on table cells
* Support for h1..h6 on table cells
* Support for nested tables
* Bugfix: thead without tr tag
* Bugfix: nested bold and italic on paragraphs or div
* Bugfix: allow <td><div>Some content <em>inside</em> a <strong>div</strong></div></td> syntax
* Bugfix: Headings in body tag are now correctly parsed
Version 0.1.7
* Allow centering of text within a paragraph if the paragraph has a 'center' class, e.g. <p class='center'>
Version 0.1.6:
* Add tables support for borders and headers
Version 0.1.5:
* Bugfix: h5 & h6 also create w:p's so any wrapping divs dont need to.
Version 0.1.4:
* Details tag doesnt really work well for printing. By default its closed and not visible until you click on the summary so for now lets ignore it in the print out.
Version 0.1.3:
* Bugfix: Leaf i and b nodes with w:p creating siblings need to create their own w:p's.
Version 0.1.2:
* Bugfix: span.h (MS Word Highlights) with sibling block elements could result in invalid wordml.
Version 0.1.1:
* Nodes with neighbor nodes that create w:p's need to be wrapped in w:p themselves.
* Fixed test suite.
Version 0.1.0:
* Rewrote xslt to support tables and updated rubyzip to v1.
Version 0.0.1:
* First basic implementation of htmltoword released.
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
# Specify your gem's dependencies in htmltoword.gemspec
gemspec
================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2013 Nicholas Frandsen
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# Ruby Html to word Gem
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.
Add this line to your application's Gemfile:
gem 'htmltoword'
And then execute:
$ bundle
Or install it yourself as:
$ gem install htmltoword
**Note:** Since version 0.4.0 the ```create``` method will return a string with the contents of the file. If you want to save the file please use ```create_and_save```. See the usage for more
### Security warnings
In versions `0.7.0` and `1.0.0` we introduced a security vulnerability when allowing
the use of local images since no check to the files was done, potentially exposing
sensitive files in the output zipfile.
Version `1.1.0` doesn't allow the use of local images but uses an insecure `open`
## Usage
### Standalone
By default, the file will be saved at the specified location. In case you want to handle the contents of the file
as a string and do what suits you best, you can specify that when calling the create function.
Using the default word file as template
```ruby
require 'htmltoword'
my_html = '<html><head></head><body><p>Hello</p></body></html>'
document = Htmltoword::Document.create(my_html)
file = Htmltoword::Document.create_and_save(my_html, file_path)
```
Using your custom word file as a template, where you can setup your own style for normal text, h1,h2, etc.
```ruby
require 'htmltoword'
# Configure the location of your custom templates
Htmltoword.config.custom_templates_path = 'some_path'
my_html = '<html><head></head><body><p>Hello</p></body></html>'
document = Htmltoword::Document.create(my_html, word_template_file_name)
file = Htmltoword::Document.create_and_save(my_html, file_path, word_template_file_name)
```
The ```create``` function will return a string with the file, so you can do with it what you consider best.
The ```create_and_save``` function will create the file in the specified file_path.
### With Rails
**For htmltoword version >= 0.2**
An action controller renderer has been defined, so there's no need to declare the mime-type and you can just respond to .docx format. It will look then for views with the extension ```.docx.erb``` which will provide the HTML that will be rendered in the Word file.
```ruby
# On your controller.
respond_to :docx
# filename and word_template are optional. By default it will name the file as your action and use the default template provided by the gem. The use of the .docx in the filename and word_template is optional.
def my_action
# ...
respond_with(@object, filename: 'my_file.docx', word_template: 'my_template.docx')
# Alternatively, if you don't want to create the .docx.erb template you could
respond_with(@object, content: '<html><head></head><body><p>Hello</p></body></html>', filename: 'my_file.docx')
end
def my_action2
# ...
respond_to do |format|
format.docx do
render docx: 'my_view', filename: 'my_file.docx'
# Alternatively, if you don't want to create the .docx.erb template you could
render docx: 'my_file.docx', content: '<html><head></head><body><p>Hello</p></body></html>'
end
end
end
```
Example of my_view.docx.erb
```
<h1> My custom template </h1>
<%= render partial: 'my_partial', collection: @objects, as: :item %>
```
Example of _my_partial.docx.erb
```
<h3><%= item.title %></h3>
<p> My html for item <%= item.id %> goes here </p>
```
**For htmltoword version <= 0.1.8**
```ruby
# Add mime-type in /config/initializers/mime_types.rb:
Mime::Type.register "application/vnd.openxmlformats-officedocument.wordprocessingml.document", :docx
# Add docx responder in your controller
def show
respond_to do |format|
format.docx do
file = Htmltoword::Document.create params[:docx_html_source], "file_name.docx"
send_file file.path, :disposition => "attachment"
end
end
end
```
```javascript
// OPTIONAL: Use a jquery click handler to store the markup in a hidden form field before the form is submitted.
// Using this strategy makes it easy to allow users to dynamically edit the document that will be turned
// into a docx file, for example by toggling sections of a document.
$('#download-as-docx').on('click', function () {
$('input[name="docx_html_source"]').val('<!DOCTYPE html>\n' + $('.delivery').html());
});
```
### Configure templates and xslt paths
From version 2.0 you can configure the location of default and custom templates and xslt files. By default templates are defined under ```lib/htmltoword/templates``` and xslt under ```lib/htmltoword/xslt```
```ruby
Htmltoword.configure do |config|
config.custom_templates_path = 'path_for_custom_templates'
# If you modify this path, there should be a 'default.docx' file in there
config.default_templates_path = 'path_for_default_template'
# If you modify this path, there should be a 'html_to_wordml.xslt' file in there
config.default_xslt_path = 'some_path'
# The use of additional custom xslt will come soon
config.custom_xslt_path = 'some_path'
end
```
## Features
All standard html elements are supported and will create the closest equivalent in wordml. For example spans will create inline elements and divs will create block like elements.
### Highlighting text
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:
```html
<span class="h" data-style="green">This text will have a green highlight</span>
```
### Page breaks
To create page breaks simply add a div with class -page-break ie:
```html
<div class="-page-break"></div>
````
### Images
Support for images is very basic and is only possible for external images(i.e accessed via URL). If the image doesn't
have correctly defined it's width and height it won't be included in the document
**Limitations:**
- Images are external i.e. pictures accessed via URL, not stored within document
- only sizing is customisable
Examples:
```html
<img src="http://placehold.it/250x100.png" style="width: 250px; height: 100px">
<img src="http://placehold.it/250x100.png" data-width="250px" data-height="100px">
<img src="http://placehold.it/250x100.png" data-height="150px" style="width:250px; height:100px">
```
## Contributing / Extending
Word docx files are essentially just a zipped collection of xml files and resources.
This gem contains a standard empty MS Word docx file and a stylesheet to transform arbitrary html into wordml.
The basic functioning of this gem can be summarised as:
1. Transform inputed html to wordml.
2. Unzip empty word docx file bundled with gem and replace its document.xml content with the new transformed result of step 1.
3. Zip up contents again into a resulting .docx file.
For more info about WordML: http://rep.oio.dk/microsoft.com/officeschemas/wordprocessingml_article.htm
Contributions would be very much appreciated.
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## License
(The MIT License)
Copyright © 2013:
* Cristina Matonte
* Nicholas Frandsen
================================================
FILE: Rakefile
================================================
require "bundler/gem_tasks"
require 'rspec/core/rake_task'
task :default => :spec
RSpec::Core::RakeTask.new
================================================
FILE: bin/htmltoword
================================================
#!/usr/bin/env ruby
require 'methadone'
require 'rmultimarkdown'
require_relative '../lib/htmltoword'
include Methadone::Main
include Methadone::CLILogging
main do |input, output|
puts "Converting #{input} to #{output}" if options[:verbose]
markup = File.read input
if options[:format] == 'markdown'
markup = markdown2html(markup)
end
Htmltoword::Document.create_and_save(markup, output, options[:template_name], options[:extras])
puts "Done" if options[:verbose]
end
def markdown2html(text)
MultiMarkdown.new(text.to_s).to_html
end
version Htmltoword::VERSION
description 'Convert simple html input (or markdown) to MS Word (docx)'
arg :input, :required
arg :output, :required
on('--verbose', '-v', 'Be verbose')
on('--extras', '-e', 'Use extra formatting features')
on('--template', '-t', 'Use custom word base template (.docx file)')
on('-f FORMAT', '--format', 'Format', /markdown|html/)
# options['ip-address'] = '127.0.0.1'
# on('-i IP_ADDRESS', '--ip-address', 'IP Address', /^\d+\.\d+\.\d+\.\d+$/)
go!
================================================
FILE: docs/styles.md
================================================
Courtesy of @fran-worley
This list is not comprehensive or tested, but I have looked through the source code, and readme and come up with the following:
## Page formatting options:
Check out: https://github.com/karnov/htmltoword/blob/master/lib/htmltoword/xslt/base.xslt
### Page Break (included in readme)
<div class="-page-break"></div>
Returns a page break
### Highlighting (included in readme)
<span class="h" data-style="chosen-color">Highlighted Text Here</span>
Will highlight text
As per: http://www.schemacentral.com/sc/ooxml/t-w_ST_HighlightColor.html these are your color choices
Valid value | Description
-------------- | ----------------
black | Black Highlighting Color
blue | Blue Highlighting Color
cyan | Cyan Highlighting Color
green | Green Highlighting Color
magenta | Magenta Highlighting Color
red | Red Highlighting Color
yellow | Yellow Highlighting Color
white | White Highlighting Color
darkBlue | Dark Blue Highlighting Color
darkCyan | Dark Cyan Highlighting Color
darkGreen | Dark Green Highlighting Color
darkMagenta | Dark Magenta Highlighting Color
darkRed | Dark Red Highlighting Color
darkYellow | Dark Yellow Highlighting Color
darkGray | Dark Gray Highlighting Color
lightGray | Light Gray Highlighting Color
none | No Text Highlighting
### Text Align (not in readme)
It looks like adding the following classes will align text in your word document appropriately.
* left
* right
* center
* justify
### HTML tags
There is also support for the following HTML tags:
* div
* p
* ul/ol, li
* b/strong
* i/em
* u
* br
* pre
* h1...h6
#### Images
It appears that at this time images are not supported see #27
#### External links
It appears that this isn't supported either yet, though there is an open pull request to add the functionality see #30
### Table formatting options
As per this: https://github.com/karnov/htmltoword/blob/master/lib/htmltoword/xslt/tables.xslt
There is basic support for tables.
You can use the following HTML tags:
* thead
* tbody
* tr
* th
* td
* h1...h6
And the following classes:
* Text alignment: (as above)
* Table borders: 'table-bordered' (Not configurable, the default is a black, single line border with a weight of 6)
* Cell borders: 'ms-border-[location]-[value]-[color - default is 000000]-[size - default is 1]'
* Cell fill: 'ms-fill-[color]'
The following are documented here: http://officeopenxml.com/WPtableCellProperties-Borders.php I do not know exactly how much of these options work in the gem, but it should at least point you in the right direction
#### [location]
Specifies where to apply the border (see Elements table in officeopenxml docs above)
Element | Description
---------- | ---------------
top | Specifies the border displayed at the top of the cell.
bottom | Specifies the border displayed at the bottom of a cell.
start | Specifies the border displayed on the leading edge of the cell (left for left-to-right tables and right for right-to-left tables). *Note:* In the previous version of the standard, this element was *left*.
end | Specifies the border displayed on the trailing edge of the cell (right for left-to-right tables and left for right-to-left tables). *Note:* In the previous version of the standard, this element was *right*.
insideH | Specifies the border to be displayed on all interior horizontal edges of the cell. Note that this is mostly useless in the case of individual cells, as there is no concept of interior edge for individual cells. However, it is used to determine cell borders to apply to a specific group of cells as part of table conditional formatting in a table style, e.g., the inside edges on the set of cells in the first column.
insideV | Specifies the border to be displayed on all interior vertical edges of the cell. Note that this is mostly useless in the case of individual cells, as there is no concept of interior edge for individual cells. However, it is used to determine cell borders to apply to a specific group of cells as part of table conditional formatting in a table style, e.g., the inside edges on the set of cells in the first column.
tl2br | Specifies the border to be displayed on the top left side to bottom right diagonal within the cell.
tr2bl | Specifies the border to be displayed on the top right to bottom left diagonal within the cell.
#### [value]
Specifies the style of the border. Possible values a per open XML docs are:
Value | Description
-------- | ---------------
single | a single line
dashDotStroked | a line with a series of alternating thin and thick strokes
dashed | a dashed line
dashSmallGap | a dashed line with small gaps
dotDash | a line with alternating dots and dashes
dotDotDash | a line with a repeating dot - dot - dash sequence
dotted | a dotted line
double | a double line
doubleWave | a double wavy line
inset | an inset set of lines
nil | no border
none | no border
outset | an outset set of lines
thick | a single line
thickThinLargeGap | a thick line contained within a thin line with a large-sized intermediate gap
thickThinMediumGap | a thick line contained within a thin line with a medium-sized intermediate gap
thickThinSmallGap | a thick line contained within a thin line with a small intermediate gap
thinThickLargeGap | a thin line contained within a thick line with a large-sized intermediate gap
thinThickMediumGap | a thick line contained within a thin line with a medium-sized intermediate gap
thinThickSmallGap | a thick line contained within a thin line with a small intermediate gap
thinThickThinLargeGap | a thin-thick-thin line with a large gap
thinThickThinMediumGap | a thin-thick-thin line with a medium gap
thinThickThinSmallGap | a thin-thick-thin line with a small gap
threeDEmboss | a three-staged gradient line, getting darker towards the paragraph
threeDEngrave | a three-staged gradient like, getting darker away from the paragraph
triple | a triple line
wave | a wavy line
#### [color]
Specifies the color of the border. Values are given as hex values (in RRGGBB format). No #, unlike hex values in HTML/CSS. E.g., color="FFFF00". A value of auto is also permitted and will allow the consuming word processor to determine the color.
#### [size]
Specifies the width of the border.
The gem seems to multiply whatever value you supply by 6. I nothing or 0 is entered then it uses 6.
================================================
FILE: docs/supported_elements.md
================================================
# Supported elements
`<Work in progress>`
## Unsupported elements
The following elements are explicitly not supported (they will be removed, before doing any transformation)
- applet
- area
- audio
- base
- basefont
- canvas
- command
- details/summary
- font
- iframe
- img
- isindex
- map
- noframes
- noscript
- object
- param
- script
- source
- style
- video
All form related elements (form, fieldset, input, label, etc.) hasn't been implemented nor deleted.
The outcome is unclear yet and it is highly probably that it will generate an invalid document.
All other elements not specified below
## Supported elements/tags
### Inline
[a](#a),
[abbr](#abbr-acronym-bdo-bdi),
[acronym](#abbr-acronym-bdo-bdi),
[b](#b-strong),
[bdi](#abbr-acronym-bdo-bdi),
[bdo](#abbr-acronym-bdo-bdi),
[big](#big-small),
[cite](#cite-dfn-em-i),
[code](#code-kbd-samp-tt-var),
[del](#del-s-strike),
[dfn](#cite-dfn-em-i),
[em](#cite-dfn-em-i),
[i](#cite-dfn-em-i),
[ins](#ins-u)
[kbd](#code-kbd-samp-tt-var),
[mark](#mark),
[q](#q),
[s](#del-s-strike),
[samp](#code-kbd-samp-tt-var),
[small](#big-small),
[span](#span),
[strike](#del-s-strike),
[strong](#b-strong),
[sub](#sub-sup),
[sup](#sub-sup)
[tt](#code-kbd-samp-tt-var),
[u](#ins-u),
[var](#code-kbd-samp-tt-var)
### Blocks
[article](#div)
[div](#div)
[p](#p)
[section](#div)
[table](#table)
[ul/ol](#lists)
#### a
Links to anchors in the same document are displayed as normal text.
Links to references starting with `http://` or `https://` will be displayed and behave as links.
#### abbr, acronym, bdo, bdi
Displayed as normal text
#### b, strong
Displayed as normal text, styled bold
#### big, small
Displayed as normal text.
Future implementation: Make the text bigger or smaller than the normal one.
#### cite, dfn, em, i
Displayed as normal text, styled italic
#### code, kbd, samp, tt, var
Displayed as normal text.
Future implementation: Assign a monospaced style, most likely using *Courier New* since it's one of the few monospaced fonts shipped with word
#### del, s, strike
Displayed as normal text with Strikethrough effect.
#### div
Divs, sections and articles are displayed as paragraphs.
Only style supported at the moment is alignment. See the wiki on [styles](https://github.com/karnov/htmltoword/wiki/Styles-and-classes) for more
#### ins, u
Displayed as normal text, using single underline style.
#### lists
Lists support is very basic. . See the wiki on [styles](https://github.com/karnov/htmltoword/wiki/Styles-and-classes) for more
Tables inside lists are NOT supported
#### mark
Displayed as normal text highlighted in yellow. See [span](#span) for more colors.
#### q
Text within `<q>text</q>` will be wrapped with double quotes `"text"`
#### span
Displayed as normal text.
When using `class="h" data-color="selected_color"` The text will be highlighted in the color specified. See the wiki on [styles](https://github.com/karnov/htmltoword/wiki/Styles-and-classes) for a list of colors
#### sub, sup
Displayed as normal text with subscript or superscript effect.
#### p
Displayed as paragraphs.
Only style supported at the moment is alignment. See the wiki on [styles](https://github.com/karnov/htmltoword/wiki/Styles-and-classes) for more
#### table
Basic support for tables. See the wiki on [styles](https://github.com/karnov/htmltoword/wiki/Styles-and-classes) for more
================================================
FILE: htmltoword.gemspec
================================================
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'htmltoword/version'
Gem::Specification.new do |spec|
spec.name = "htmltoword"
spec.version = Htmltoword::VERSION
spec.authors = ["Nicholas Frandsen, Cristina Matonte"]
spec.email = ["nick.rowe.frandsen@gmail.com, anitsirc1@gmail.com"]
spec.description = %q{Convert html to word docx document.}
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.}
spec.homepage = "http://github.com/karnov/htmltoword"
spec.license = "MIT"
spec.files = Dir.glob("lib/**/*.{rb,xslt,docx}") + %w{ bin/htmltoword README.md Rakefile }
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "actionpack"
spec.add_dependency "nokogiri"
spec.add_dependency "rubyzip", ">= 1.0"
spec.add_development_dependency "rspec"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "methadone"
spec.add_development_dependency "rmultimarkdown"
end
================================================
FILE: lib/htmltoword/configuration.rb
================================================
module Htmltoword
class Configuration
attr_accessor :default_templates_path, :custom_templates_path, :default_xslt_path, :custom_xslt_path
def initialize
@default_templates_path = File.join(File.expand_path('../', __FILE__), 'templates')
@custom_templates_path = File.join(File.expand_path('../', __FILE__), 'templates')
@default_xslt_path = File.join(File.expand_path('../', __FILE__), 'xslt')
@custom_xslt_path = File.join(File.expand_path('../', __FILE__), 'xslt')
end
end
end
================================================
FILE: lib/htmltoword/document.rb
================================================
module Htmltoword
class Document
include XSLTHelper
class << self
include TemplatesHelper
def create(content, template_name = nil, extras = false)
template_name += extension if template_name && !template_name.end_with?(extension)
document = new(template_file(template_name))
document.replace_files(content, extras)
document.generate
end
def create_and_save(content, file_path, template_name = nil, extras = false)
File.open(file_path, 'wb') do |out|
out << create(content, template_name, extras)
end
end
def create_with_content(template, content, extras = false)
template += extension unless template.end_with?(extension)
document = new(template_file(template))
document.replace_files(content, extras)
document.generate
end
def extension
'.docx'
end
def doc_xml_file
'word/document.xml'
end
def numbering_xml_file
'word/numbering.xml'
end
def relations_xml_file
'word/_rels/document.xml.rels'
end
def content_types_xml_file
'[Content_Types].xml'
end
end
def initialize(template_path)
@replaceable_files = {}
@template_path = template_path
@image_files = []
end
#
# Generate a string representing the contents of a docx file.
#
def generate
Zip::File.open(@template_path) do |template_zip|
buffer = Zip::OutputStream.write_buffer do |out|
template_zip.each do |entry|
out.put_next_entry entry.name
if @replaceable_files[entry.name] && entry.name == Document.doc_xml_file
source = entry.get_input_stream.read
# Change only the body of document. TODO: Improve this...
source = source.sub(/(<w:body>)((.|\n)*?)(<w:sectPr)/, "\\1#{@replaceable_files[entry.name]}\\4")
out.write(source)
elsif @replaceable_files[entry.name]
out.write(@replaceable_files[entry.name])
elsif entry.name == Document.content_types_xml_file
raw_file = entry.get_input_stream.read
content_types = @image_files.empty? ? raw_file : inject_image_content_types(raw_file)
out.write(content_types)
else
out.write(template_zip.read(entry.name))
end
end
unless @image_files.empty?
#stream the image files into the media folder using open-uri
@image_files.each do |hash|
out.put_next_entry("word/media/#{hash[:filename]}")
URI.open(hash[:url], 'rb') do |f|
out.write(f.read)
end
end
end
end
buffer.string
end
end
def replace_files(html, extras = false)
html = '<body></body>' if html.nil? || html.empty?
original_source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
source = xslt(stylesheet_name: 'cleanup').transform(original_source)
transform_and_replace(source, xslt_path('numbering'), Document.numbering_xml_file)
transform_and_replace(source, xslt_path('relations'), Document.relations_xml_file)
transform_doc_xml(source, extras)
local_images(source)
end
def transform_doc_xml(source, extras = false)
transformed_source = xslt(stylesheet_name: 'cleanup').transform(source)
transformed_source = xslt(stylesheet_name: 'inline_elements').transform(transformed_source)
transform_and_replace(transformed_source, document_xslt(extras), Document.doc_xml_file, extras)
end
private
def transform_and_replace(source, stylesheet_path, file, remove_ns = false)
stylesheet = xslt(stylesheet_path: stylesheet_path)
content = stylesheet.apply_to(source)
content.gsub!(/\s*xmlns:(\w+)="(.*?)\s*"/, '') if remove_ns
@replaceable_files[file] = content
end
#generates an array of hashes with filename and full url
#for all images to be embeded in the word document
def local_images(source)
source.css('img').each_with_index do |image,i|
filename = image['data-filename'] ? image['data-filename'] : image['src'].split("/").last
ext = File.extname(filename).delete(".").downcase
@image_files << { filename: "image#{i+1}.#{ext}", url: image['src'], ext: ext }
end
end
#get extension from filename and clean to match content_types
def content_type_from_extension(ext)
ext == "jpg" ? "jpeg" : ext
end
#inject the required content_types into the [content_types].xml file...
def inject_image_content_types(source)
doc = Nokogiri::XML(source)
#get a list of all extensions currently in content_types file
existing_exts = doc.css("Default").map { |node| node.attribute("Extension").value }.compact
#get a list of extensions we need for our images
required_exts = @image_files.map{ |i| i[:ext] }
#workout which required extensions are missing from the content_types file
missing_exts = (required_exts - existing_exts).uniq
#inject missing extensions into document
missing_exts.each do |ext|
doc.at_css("Types").add_child( "<Default Extension='#{ext}' ContentType='image/#{content_type_from_extension(ext)}'/>")
end
#return the amended source to be saved into the zip
doc.to_s
end
end
end
================================================
FILE: lib/htmltoword/helpers/templates_helper.rb
================================================
module Htmltoword
module TemplatesHelper
def template_file(template_file_name = nil)
default_path = File.join(::Htmltoword.config.default_templates_path, 'default.docx')
template_path = template_file_name.nil? ? '' : File.join(::Htmltoword.config.custom_templates_path, template_file_name)
File.exist?(template_path) ? template_path : default_path
end
end
end
================================================
FILE: lib/htmltoword/helpers/xslt_helper.rb
================================================
module Htmltoword
module XSLTHelper
def document_xslt(extras = false)
file_name = extras ? 'htmltoword' : 'base'
xslt_path(file_name)
end
def xslt_path(template_name)
File.join(Htmltoword.config.default_xslt_path, "#{template_name}.xslt")
end
def xslt(stylesheet_name: nil, stylesheet_path: nil)
return Nokogiri::XSLT(File.open(stylesheet_path)) if stylesheet_path
Nokogiri::XSLT(File.open(xslt_path(stylesheet_name)))
end
end
end
================================================
FILE: lib/htmltoword/railtie.rb
================================================
module Htmltoword
class Railtie < ::Rails::Railtie
initializer 'htmltoword.setup' do
if defined?(Mime) and Mime[:docx].nil?
Mime::Type.register 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', :docx
end
ActionController::Renderers.add :docx do |file_name, options|
Htmltoword::Renderer.send_file(self, file_name, options)
end
if defined? ActionController::Responder
ActionController::Responder.class_eval do
def to_docx
if @default_response
@default_response.call(options)
else
controller.render({ docx: controller.action_name }.merge(options))
end
end
end
end
end
end
end
================================================
FILE: lib/htmltoword/renderer.rb
================================================
module Htmltoword
class Renderer
class << self
def send_file(context, filename, options = {})
new(context, filename, options).send_file
end
end
def initialize(context, filename, options)
@word_template = options[:word_template].presence
@disposition = options.fetch(:disposition, 'attachment')
@use_extras = options.fetch(:extras, false)
@file_name = file_name(filename, options)
@context = context
define_template(filename, options)
@content = options[:content] || @context.render_to_string(options)
end
def send_file
document = Htmltoword::Document.create(@content, @word_template, @use_extras)
@context.send_data(document, filename: @file_name, type: Mime[:docx], disposition: @disposition)
end
private
def define_template(filename, options)
if options[:template] == @context.action_name
if filename =~ %r{^([^\/]+)/(.+)$}
options[:prefixes] ||= []
options[:prefixes].unshift $1
options[:template] = $2
else
options[:template] = filename
end
end
end
def file_name(filename, options)
name = options[:filename].presence || filename
name =~ /\.docx$/ ? name : "#{name}.docx"
end
end
end
================================================
FILE: lib/htmltoword/version.rb
================================================
module Htmltoword
VERSION = '1.1.1'
end
================================================
FILE: lib/htmltoword/xslt/base.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
<xsl:include href="./functions.xslt"/>
<xsl:include href="./tables.xslt"/>
<xsl:include href="./links.xslt"/>
<xsl:include href="./images.xslt"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="head" />
<xsl:template match="body">
<xsl:comment>
KNOWN BUGS:
div
h2
div
textnode (WONT BE WRAPPED IN A W:P)
div
table
span
text
</xsl:comment>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="body/*[not(*)]">
<w:p>
<xsl:call-template name="text-alignment" />
<w:r>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:p>
</xsl:template>
<xsl:template match="br[not(ancestor::p) and not(ancestor::div) and not(ancestor::td|ancestor::li) or
(preceding-sibling::div or following-sibling::div or preceding-sibling::p or following-sibling::p)]">
<w:p>
<w:r></w:r>
</w:p>
</xsl:template>
<xsl:template match="br[(ancestor::li or ancestor::td) and
(preceding-sibling::div or following-sibling::div or preceding-sibling::p or following-sibling::p)]">
<w:r>
<w:br />
</w:r>
</xsl:template>
<xsl:template match="br">
<w:r>
<w:br />
</w:r>
</xsl:template>
<xsl:template match="pre">
<w:p>
<xsl:apply-templates />
</w:p>
</xsl:template>
<xsl:template match="div[not(ancestor::li) and not(ancestor::td) and not(ancestor::th) and not(ancestor::p) and not(ancestor::dl) and not(descendant::dl) 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::h5) and not(descendant::h6) and not(descendant::table) and not(descendant::li) and not (descendant::pre)]">
<xsl:comment>Divs should create a p if nothing above them has and nothing below them will</xsl:comment>
<w:p>
<xsl:call-template name="text-alignment" />
<xsl:apply-templates />
</w:p>
</xsl:template>
<xsl:template match="div">
<xsl:apply-templates />
</xsl:template>
<!-- TODO: make this prettier. Headings shouldn't enter in template from L51 -->
<xsl:template match="body/h1|body/h2|body/h3|body/h4|body/h5|body/h6|h1|h2|h3|h4|h5|h6">
<xsl:variable name="length" select="string-length(name(.))"/>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading{substring(name(.),$length)}"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:p>
</xsl:template>
<xsl:template match="p[not(ancestor::li)]">
<w:p>
<xsl:call-template name="text-alignment" />
<xsl:apply-templates />
</w:p>
</xsl:template>
<xsl:template match="ol|ul">
<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"/>
<xsl:apply-templates>
<xsl:with-param name="global_level" select="$global_level" />
</xsl:apply-templates>
</xsl:template>
<xsl:template name="listItem" match="li">
<xsl:param name="global_level" />
<xsl:param name="preceding-siblings" select="0"/>
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::br">
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"></w:pStyle>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r></w:r>
</w:p>
</xsl:when>
<xsl:when test="self::ol|self::ul">
<xsl:apply-templates>
<xsl:with-param name="global_level" select="$global_level" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="not(descendant::li)"> <!-- simpler div, p, headings, etc... -->
<xsl:variable name="ilvl" select="count(ancestor::ol) + count(ancestor::ul) - 1"></xsl:variable>
<xsl:choose>
<xsl:when test="$preceding-siblings + count(preceding-sibling::*) > 0">
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"></w:pStyle>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="{720 * ($ilvl + 1)}"/>
</w:pPr>
<xsl:apply-templates/>
</w:p>
</xsl:when>
<xsl:otherwise>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"></w:pStyle>
<w:numPr>
<w:ilvl w:val="{$ilvl}"/>
<w:numId w:val="{$global_level}"/>
</w:numPr>
</w:pPr>
<xsl:apply-templates/>
</w:p>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise> <!-- mixed things div having list and stuff content... -->
<xsl:call-template name="listItem">
<xsl:with-param name="global_level" select="$global_level" />
<xsl:with-param name="preceding-siblings" select="$preceding-siblings + count(preceding-sibling::*)" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="dl">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="dt">
<w:p>
<xsl:apply-templates/>
</w:p>
</xsl:template>
<xsl:template match="dd">
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<xsl:apply-templates/>
</w:p>
</xsl:template>
<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)]
|a[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)]
|small[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)]
|strong[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)]
|em[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)]
|i[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)]
|b[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)]
|u[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)]">
<xsl:comment>
In the following situation:
div
h2
span
textnode
span
textnode
p
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.
</xsl:comment>
<w:p>
<xsl:choose>
<xsl:when test="self::a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]">
<xsl:call-template name="link" />
</xsl:when>
<xsl:when test="self::img">
<xsl:comment>
This template adds images.
</xsl:comment>
<xsl:call-template name="image"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</w:p>
</xsl:template>
<xsl:template match="text()[not(parent::li) and not(parent::td) and not(parent::pre) 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)]">
<xsl:comment>
In the following situation:
div
h2
textnode
p
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.
</xsl:comment>
<w:p>
<w:r>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:p>
</xsl:template>
<xsl:template match="span[contains(concat(' ', @class, ' '), ' h ')]">
<xsl:comment>
This template adds MS Word highlighting ability.
</xsl:comment>
<xsl:variable name="color">
<xsl:choose>
<xsl:when test="./@data-style='pink'">magenta</xsl:when>
<xsl:when test="./@data-style='blue'">cyan</xsl:when>
<xsl:when test="./@data-style='orange'">darkYellow</xsl:when>
<xsl:otherwise><xsl:value-of select="./@data-style"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="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">
<w:p>
<w:r>
<w:rPr>
<w:highlight w:val="{$color}"/>
</w:rPr>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:p>
</xsl:when>
<xsl:otherwise>
<w:r>
<w:rPr>
<w:highlight w:val="{$color}"/>
</w:rPr>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="div[contains(concat(' ', @class, ' '), ' -page-break ')]">
<w:p>
<w:r>
<w:br w:type="page" />
</w:r>
</w:p>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="details" />
<xsl:template match="text()">
<xsl:if test="string-length(.) > 0">
<w:r>
<xsl:if test="ancestor::i">
<w:rPr>
<w:i />
</w:rPr>
</xsl:if>
<xsl:if test="ancestor::b">
<w:rPr>
<w:b />
</w:rPr>
</xsl:if>
<xsl:if test="ancestor::u">
<w:rPr>
<w:u w:val="single"/>
</w:rPr>
</xsl:if>
<xsl:if test="ancestor::s">
<w:rPr>
<w:strike w:val="true"/>
</w:rPr>
</xsl:if>
<xsl:if test="ancestor::sub">
<w:rPr>
<w:vertAlign w:val="subscript"/>
</w:rPr>
</xsl:if>
<xsl:if test="ancestor::sup">
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
</xsl:if>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</xsl:if>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template name="text-alignment">
<xsl:param name="class" select="@class" />
<xsl:param name="style" select="@style" />
<xsl:variable name="alignment">
<xsl:choose>
<xsl:when test="contains(concat(' ', $class, ' '), ' center ') or contains(translate(normalize-space($style),' ',''), 'text-align:center')">center</xsl:when>
<xsl:when test="contains(concat(' ', $class, ' '), ' right ') or contains(translate(normalize-space($style),' ',''), 'text-align:right')">right</xsl:when>
<xsl:when test="contains(concat(' ', $class, ' '), ' left ') or contains(translate(normalize-space($style),' ',''), 'text-align:left')">left</xsl:when>
<xsl:when test="contains(concat(' ', $class, ' '), ' justify ') or contains(translate(normalize-space($style),' ',''), 'text-align:justify')">both</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="string-length(normalize-space($alignment)) > 0">
<w:pPr>
<w:jc w:val="{$alignment}"/>
</w:pPr>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/cleanup.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="head"/>
<!-- Elements not supported -->
<xsl:template match="applet"/>
<xsl:template match="area"/>
<xsl:template match="audio"/>
<xsl:template match="base"/>
<xsl:template match="basefont"/>
<xsl:template match="canvas"/>
<xsl:template match="command"/>
<xsl:template match="font"/>
<xsl:template match="iframe"/>
<xsl:template match="img[not(starts-with(@src, 'http://')) and not(starts-with(@src, 'https://'))]"/>
<xsl:template match="isindex"/>
<xsl:template match="map"/>
<xsl:template match="noframes"/>
<xsl:template match="noscript"/>
<xsl:template match="object"/>
<xsl:template match="param"/>
<xsl:template match="script"/>
<xsl:template match="source"/>
<xsl:template match="style"/>
<xsl:template match="video"/>
<!-- Elements currently being handled as normal text. Remove tags only -->
<xsl:template match="abbr"><xsl:apply-templates/></xsl:template>
<xsl:template match="acronym"><xsl:apply-templates/></xsl:template>
<xsl:template match="bdi"><xsl:apply-templates/></xsl:template>
<xsl:template match="bdo"><xsl:apply-templates/></xsl:template>
<xsl:template match="big"><xsl:apply-templates/></xsl:template>
<xsl:template match="code"><xsl:apply-templates/></xsl:template>
<xsl:template match="kbd"><xsl:apply-templates/></xsl:template>
<xsl:template match="samp"><xsl:apply-templates/></xsl:template>
<xsl:template match="small"><xsl:apply-templates/></xsl:template>
<xsl:template match="tt"><xsl:apply-templates/></xsl:template>
<xsl:template match="var"><xsl:apply-templates/></xsl:template>
<!-- Inline elements transformations -->
<xsl:template match="cite"><i><xsl:apply-templates/></i></xsl:template>
<xsl:template match="del"><s><xsl:apply-templates/></s></xsl:template>
<xsl:template match="dfn"><i><xsl:apply-templates/></i></xsl:template>
<xsl:template match="em"><i><xsl:apply-templates/></i></xsl:template>
<xsl:template match="ins"><u><xsl:apply-templates/></u></xsl:template>
<xsl:template match="mark"><span class="h" data-style="yellow"><xsl:apply-templates/></span></xsl:template>
<xsl:template match="q">"<xsl:apply-templates/>"</xsl:template>
<xsl:template match="strike"><s><xsl:apply-templates/></s></xsl:template>
<xsl:template match="strong"><b><xsl:apply-templates/></b></xsl:template>
<!-- Block elements transformations -->
<xsl:template match="section"><div class="{@class}" style="{@style}"><xsl:apply-templates/></div></xsl:template>
<xsl:template match="article"><div class="{@class}" style="{@style}"><xsl:apply-templates/></div></xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/extras.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<!-- use block quotes for spacing (can be nested) -->
<xsl:template match="blockquote">
<w:p>
<w:r></w:r>
</w:p>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/functions.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<!-- support function to return substring-before or everything -->
<func:function name="func:substring-before-if-contains">
<xsl:param name="arg"/>
<xsl:param name="delim"/>
<func:result>
<xsl:choose>
<xsl:when test="contains($arg, $delim)">
<xsl:value-of select="substring-before($arg, $delim)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$arg"/>
</xsl:otherwise>
</xsl:choose>
</func:result>
</func:function>
<!-- template as function used to return the relationship id of the element (currently links or images) -->
<xsl:template name="relationship-id">rId<xsl:value-of select="count(preceding::a[starts-with(@href, 'http://') or starts-with(@href, 'https://')])+count(preceding::img)+8"/></xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/htmltoword.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:import href="./base.xslt"/>
<!--Extra templates and customizations-->
<xsl:include href="./extras.xslt"/>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/image_functions.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<!-- template as function used to return the file extension of an image. -->
<xsl:template name="image-extension">
<xsl:param name="data-filename" select="." />
<xsl:param name="source" select="." />
<xsl:variable name="filename">
<xsl:call-template name="image-name">
<xsl:with-param name="source" select="$source"/>
<xsl:with-param name="data-filename" select="$data-filename"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="substring-after($filename,'.')"/>
</xsl:template>
<!-- template as function used to return the name of an image. -->
<xsl:template name="image-name">
<xsl:param name="data-filename" select="." />
<xsl:param name="source" select="." />
<xsl:choose>
<xsl:when test="string-length($data-filename) > 0">
<xsl:value-of select="$data-filename"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="extract-filename-from-path">
<xsl:with-param name="path" select="$source"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- template as function used to extract the filename from the image source. Can't use tokenize or other functions which return a fragment tree as xpath can't process them. -->
<xsl:template name="extract-filename-from-path">
<xsl:param name="path" select="." />
<xsl:choose>
<xsl:when test="not(contains($path, '/'))">
<xsl:value-of select="$path" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="extract-filename-from-path">
<xsl:with-param name="path" select="substring-after($path, '/')" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--
Returns the unqualified dimension from a length specification copied from:
http://docbook.sourceforge.net/release/xsl/1.76.1/doc/lib/length-magnitude.html
-->
<xsl:template name="length-magnitude">
<xsl:param name="length" select="'0pt'"></xsl:param>
<xsl:choose>
<xsl:when test="string-length($length) = 0"></xsl:when>
<xsl:when test="substring($length,1,1) = '0' or substring($length,1,1) = '1' or substring($length,1,1) = '2' or substring($length,1,1) = '3' or substring($length,1,1) = '4' or substring($length,1,1) = '5' or substring($length,1,1) = '6' or substring($length,1,1) = '7' or substring($length,1,1) = '8' or substring($length,1,1) = '9' or substring($length,1,1) = '.'">
<xsl:value-of select="substring($length,1,1)"></xsl:value-of>
<xsl:call-template name="length-magnitude">
<xsl:with-param name="length" select="substring($length,2)"></xsl:with-param>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- Convert em and pixel sizes to inches. Inspired by from:
http://docbook.sourceforge.net/release/xsl/1.76.1/doc/lib/length-in-points.html
EMU info from: https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/
-->
<xsl:template name="length-in-emus">
<xsl:param name="length" select="'0px'"/>
<xsl:param name="em.size" select="6.02250006023"/>
<xsl:param name="pixels.per.inch" select="90"/>
<xsl:variable name="emus.per.inch" select="914400"/>
<xsl:variable name="magnitude">
<xsl:call-template name="length-magnitude">
<xsl:with-param name="length" select="$length"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="units">
<xsl:value-of select="substring($length, string-length($magnitude)+1)"/>
</xsl:variable>
<xsl:variable name="inches">
<xsl:choose>
<xsl:when test="$units = 'px'">
<xsl:value-of select="$magnitude div $pixels.per.inch"/>
</xsl:when>
<xsl:when test="$units = 'em'">
<xsl:value-of select="$magnitude div $em.size"/>
</xsl:when>
<xsl:otherwise>
<xsl:message>
<xsl:text>Unrecognized unit of measure: </xsl:text>
<xsl:value-of select="$units"></xsl:value-of>
<xsl:text>.</xsl:text>
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$inches * $emus.per.inch"/>
</xsl:template>
<!-- template as function used to get the width or height of an image in points. -->
<xsl:template name="image-dimention">
<xsl:param name="style" />
<xsl:param name="data-value" />
<xsl:param name="type" />
<xsl:variable name="size">
<xsl:choose>
<xsl:when test="string-length($data-value) > 0">
<xsl:value-of select="$data-value" />
</xsl:when>
<xsl:when test="contains($style, concat($type,':'))">
<xsl:value-of select="translate(str:tokenize(substring-after($style, concat($type,':')), ';')[1],' 	
','')" />
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="length-in-emus">
<xsl:with-param name="length" select="$size"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/images.xslt
================================================
<xsl:stylesheet 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:w15="http://schemas.microsoft.com/office/word/2012/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:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"
xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
mc:Ignorable="w14 w15 wp14 a14"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:include href="./image_functions.xslt"/>
<xsl:template match="img|body/img" name="image">
<xsl:choose>
<xsl:when test="not(@data-width) and not(@data-height) and not(contains(@style, 'width')) and not(contains(@style, 'height'))">
<!-- Do not transfor images unless width and height are correctly specified -->
</xsl:when>
<xsl:otherwise>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent>
<xsl:call-template name="image-dimention-attributes"/>
</wp:extent>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr>
<xsl:attribute name="id"><xsl:value-of select="count(preceding::img)+1" /></xsl:attribute>
<xsl:attribute name="name">Picture <xsl:value-of select="count(preceding::img)+1" /></xsl:attribute>
</wp:docPr>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic>
<pic:nvPicPr>
<pic:cNvPr>
<xsl:attribute name="id"><xsl:value-of select="count(preceding::img)+1" /></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="@alt" /></xsl:attribute>
<xsl:attribute name="name"><xsl:call-template name="image-name">
<xsl:with-param name="source" select="@src"/>
<xsl:with-param name="data-filename" select="@data-filename"/>
</xsl:call-template></xsl:attribute>
</pic:cNvPr>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip>
<xsl:attribute name="r:embed"><xsl:call-template name="relationship-id"/></xsl:attribute>
<a:extLst>
<a:ext uri="{{28A0092B-C50C-407E-A947-70E740481C1C}}">
<a14:useLocalDpi val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext>
<xsl:call-template name="image-dimention-attributes"/>
</a:ext>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--
A style specifiying the width and height is required to render an image correctly in word.
Styles can be provided either via data attributes:
img src="pathtosomeimage" data-width="200px" data-height="250px"
or via the html style attribute
img src="pathtosomeimage" style="width:150px;height:200px"
If both a style and data attributes are provided then data attributes take president.
e.g.
img src="pathtosomeimage" data-width="200em" style="width:150px;height:200px"
becomes: width:200em;height:200px
Note: All sizes must be in pixles or em
-->
<xsl:template name="image-dimention-attributes">
<xsl:attribute name="cx">
<xsl:call-template name="image-dimention">
<xsl:with-param name="style" select="@style" />
<xsl:with-param name="data-value" select="@data-width" />
<xsl:with-param name="type" select="'width'" />
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="cy">
<xsl:call-template name="image-dimention">
<xsl:with-param name="style" select="@style" />
<xsl:with-param name="data-value" select="@data-height" />
<xsl:with-param name="type" select="'height'" />
</xsl:call-template>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/inline_elements.xslt
================================================
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<!-- get first inline element of a sequence or text having block element siblings... -->
<xsl:template match="node()[self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()][parent::div|parent::li|parent::td]">
<div>
<xsl:attribute name="class"><xsl:value-of select="../@class"/></xsl:attribute>
<xsl:attribute name="style"><xsl:value-of select="../@style"/></xsl:attribute>
<xsl:call-template name="inlineElement"/>
</div>
<xsl:apply-templates select="following-sibling::node()[not((self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text())[parent::div|parent::li|parent::td])][1]"/>
</xsl:template>
<!-- get following inline elements... -->
<xsl:template match="
a[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|b[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|i[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|s[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|span[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|sub[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|sup[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|u[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]
|text()[preceding-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]]"
name="inlineElement">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1][self::a|self::b|self::i|self::s|self::span|self::sub|self::sup|self::u|self::text()]"/>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/links.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:template match="a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]" name="link">
<w:hyperlink>
<xsl:attribute name="r:id"><xsl:call-template name="relationship-id"/></xsl:attribute>
<w:r>
<w:rPr>
<w:rStyle w:val="Hyperlink"/>
<w:color w:val="000080"/>
<w:u w:val="single"/>
</w:rPr>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:hyperlink>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/numbering.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
<xsl:include href="./functions.xslt"/>
<func:function name="func:list-type">
<xsl:param name="tag_name"/>
<xsl:param name="style"/>
<xsl:param name="class"/>
<func:result>
<xsl:choose>
<xsl:when test="contains($style, 'list-style-type:') or string-length(normalize-space($class)) > 0">
<xsl:variable name="lstyle" select="func:substring-before-if-contains(substring-after($style, 'list-style-type:'), ';')"/>
<xsl:choose>
<xsl:when test="contains($lstyle, 'lower-alpha') or contains($lstyle, 'lower-latin') or contains($class, 'alfalower')">lowerLetter</xsl:when>
<xsl:when test="contains($lstyle, 'upper-alpha') or contains($lstyle, 'upper-latin') or contains($class, 'alfaupper')">upperLetter</xsl:when>
<xsl:when test="contains($lstyle, 'lower-roman') or contains($class, 'romanlower')">lowerRoman</xsl:when>
<xsl:when test="contains($lstyle, 'upper-roman') or contains($class, 'romanupper')">upperRoman</xsl:when>
<xsl:when test="contains($lstyle, 'none') or contains($class, 'manuell')">none</xsl:when>
<xsl:when test="contains($lstyle, 'decimal') or contains($class, 'num') or contains($class, 'token')">decimal</xsl:when>
<xsl:when test="contains($lstyle, 'disc')">bullet,●</xsl:when>
<xsl:when test="contains($lstyle, 'circle')">bullet,o</xsl:when>
<xsl:when test="contains($lstyle, 'square')">bullet,■</xsl:when>
<xsl:otherwise>none</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$tag_name = 'ol'">decimal</xsl:when>
<xsl:otherwise>bullet,●</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</func:result>
</func:function>
<xsl:template match="/">
<w:numbering 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">
<xsl:apply-templates />
<xsl:variable name="nlists" select="count(//ol[not(ancestor::ol) and not(ancestor::ul)]) + count(//ul[not(ancestor::ol) and not(ancestor::ul)])"/>
<xsl:call-template name="define-abstractNum"/>
</w:numbering>
</xsl:template>
<xsl:template name="container" match="ol|ul">
<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"/>
<xsl:variable name="style" select="func:list-type(name(.), concat(' ', @style, ' '), concat(' ', @class, ' '))"/>
<xsl:choose>
<xsl:when test="not(ancestor::ol or ancestor::ul)">
<w:abstractNum w:abstractNumId="{$global_level - 1}">
<w:nsid w:val="{concat('099A08C', $global_level)}"/>
<w:multiLevelType w:val="hybridMultilevel"/>
<xsl:call-template name="numbering_level">
<xsl:with-param name="ilvl" select="0"/>
<xsl:with-param name="style" select="$style"/>
</xsl:call-template>
<xsl:call-template name="item"/>
<xsl:if test="count(.//ol|.//ul) < 6">
<xsl:call-template name="autocomplete">
<xsl:with-param name="ilvl" select="count(.//ol) + count(.//ul)"/>
<xsl:with-param name="style" select="$style"/>
</xsl:call-template>
</xsl:if>
</w:abstractNum>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="numbering_level">
<xsl:with-param name="ilvl" select="count(ancestor::ol) + count(ancestor::ul)"/>
<xsl:with-param name="style" select="$style"/>
</xsl:call-template>
<xsl:call-template name="item"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="item">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::ol|self::ul">
<xsl:call-template name="container"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="item"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()"/>
<xsl:template name="numbering_level">
<xsl:param name="style" />
<xsl:param name="ilvl" />
<w:lvl w:ilvl="{$ilvl}">
<w:start w:val="1"/>
<w:numFmt w:val="{func:substring-before-if-contains($style, ',')}"/>
<xsl:choose>
<xsl:when test="contains($style, 'bullet')">
<xsl:variable name="list-symbol" select="substring-after($style, ',')"/>
<w:lvlText w:val="{$list-symbol}"/>
</xsl:when>
<xsl:when test="$style = 'none'">
<w:lvlText w:val=""/>
</xsl:when>
<xsl:otherwise>
<w:lvlText w:val="%{$ilvl + 1}."/>
</xsl:otherwise>
</xsl:choose>
<w:lvlJc w:val="left"/>
<w:pPr>
<w:ind w:left="{720 * ($ilvl + 1)}" w:hanging="360"/>
</w:pPr>
<xsl:if test="contains($style, 'bullet')">
<w:rPr>
<w:rFonts w:ascii="Symbol" w:hAnsi="Symbol" w:hint="default"/>
</w:rPr>
</xsl:if>
</w:lvl>
</xsl:template>
<xsl:template name="autocomplete">
<xsl:param name="ilvl"/>
<xsl:param name="style" />
<xsl:variable name="current_level">
<xsl:choose>
<xsl:when test="$ilvl < 1">1</xsl:when>
<xsl:otherwise><xsl:value-of select="$ilvl"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$current_level < 6">
<xsl:call-template name="numbering_level">
<xsl:with-param name="ilvl" select="$current_level"/>
<xsl:with-param name="style" select="$style"/>
</xsl:call-template>
<xsl:call-template name="autocomplete">
<xsl:with-param name="ilvl" select="$current_level + 1"/>
<xsl:with-param name="style" select="$style"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="define-abstractNum">
<xsl:param name="current" select="0"/>
<xsl:param name="max" select="count(//ol[not(ancestor::ol) and not(ancestor::ul)]) + count(//ul[not(ancestor::ol) and not(ancestor::ul)])"/>
<xsl:if test="$current < $max">
<w:num w:numId="{$current + 1}">
<w:abstractNumId w:val="{$current}"/>
</w:num>
<xsl:call-template name="define-abstractNum">
<xsl:with-param name="current" select="$current + 1"/>
<xsl:with-param name="max" select="$max"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/relations.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://schemas.openxmlformats.org/package/2006/relationships"
version="1.0">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes" />
<xsl:include href="./image_functions.xslt"/>
<xsl:include href="./functions.xslt"/>
<xsl:template match="a[starts-with(@href, 'http://') or starts-with(@href, 'https://')]" priority="1">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="{@href}" TargetMode="External">
<xsl:attribute name="Id"><xsl:call-template name="relationship-id"/></xsl:attribute>
</Relationship>
</xsl:template>
<!--
Images can either be embedded in the document or referenced via the external url.
By default images are embedded and a copy will be stored in the final zip folder.
If you want your images to be referenced externally (don't store the image files) then add data-external="true" to your image tag(s).
If you are embedding them images need a filename. You can either define one by passing the name and extension to data-filename or rely on the defaul which is the last part of the source url.
**Word files can be corrupted if an extension isn't present so if you are relying on the source url ensure that is has an extension.**
-->
<xsl:template match="img" priority="0">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image">
<xsl:choose>
<xsl:when test="@data-external = 'true'">
<xsl:attribute name="Target"><xsl:value-of select="@src"/></xsl:attribute>
<xsl:attribute name="TargetMode">External</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="Target">media/image<xsl:value-of select="count(preceding::img)+1"/>.<xsl:call-template name="image-extension">
<xsl:with-param name="source" select="@src"/>
<xsl:with-param name="data-filename" select="@data-filename"/>
</xsl:call-template>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:attribute name="Id"><xsl:call-template name="relationship-id"/></xsl:attribute>
</Relationship>
</xsl:template>
<xsl:template match="/">
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships>
<Relationship Id="rId3" Type="http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects" Target="stylesWithEffects.xml"/>
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Target="numbering.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
<xsl:apply-templates select="*"/>
</Relationships>
</xsl:template>
<xsl:template match="text()|@*"/>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/style2.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/common"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="no" indent="yes" />
<xsl:template match="/ | html">
<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">
<xsl:apply-templates select="//body"/>
</w:document>
</xsl:template>
<xsl:template match="body">
<w:body>
<w:p>
<xsl:apply-templates/>
</w:p>
<w:sectPr>
<w:pgSz w:w="11906" w:h="16838"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
<w:cols w:space="708"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
</xsl:template>
<xsl:template match="h1|h2|h3|li|span">
<w:br/>
<w:r>
<xsl:comment>Im block</xsl:comment>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
<w:br/>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword/xslt/tables.xslt
================================================
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:WX="http://schemas.microsoft.com/office/word/2003/auxHint"
xmlns:aml="http://schemas.microsoft.com/aml/2001/core"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ext="http://www.xmllab.net/wordml2html/ext"
xmlns:java="http://xml.apache.org/xalan/java"
xmlns:str="http://exslt.org/strings"
xmlns:func="http://exslt.org/functions"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
version="1.0"
exclude-result-prefixes="java msxsl ext w o v WX aml w10"
extension-element-prefixes="func">
<!--XSLT support for tables -->
<!-- Full width tables per default -->
<xsl:template match="table">
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<xsl:call-template name="tableborders"/>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<xsl:apply-templates />
</w:tbl>
</xsl:template>
<xsl:template match="tbody">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="thead">
<xsl:choose>
<xsl:when test="count(./tr) = 0">
<w:tr><xsl:apply-templates /></w:tr>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="tr">
<xsl:if test="string-length(.) > 0">
<w:tr>
<xsl:apply-templates />
</w:tr>
</xsl:if>
</xsl:template>
<xsl:template match="th">
<w:tc>
<xsl:call-template name="table-cell-properties"/>
<w:p>
<w:r>
<w:rPr>
<w:b />
</w:rPr>
<w:t xml:space="preserve"><xsl:value-of select="."/></w:t>
</w:r>
</w:p>
</w:tc>
</xsl:template>
<xsl:template match="td">
<w:tc>
<xsl:call-template name="table-cell-properties"/>
<xsl:call-template name="block">
<xsl:with-param name="current" select="." />
<xsl:with-param name="class" select="@class" />
<xsl:with-param name="style" select="@style" />
</xsl:call-template>
</w:tc>
</xsl:template>
<xsl:template name="block">
<xsl:param name="current" />
<xsl:param name="class" />
<xsl:param name="style" />
<xsl:if test="count($current/*|$current/text()) = 0">
<w:p/>
</xsl:if>
<xsl:for-each select="$current/*|$current/text()">
<xsl:choose>
<xsl:when test="name(.) = 'table'">
<xsl:apply-templates select="." />
<w:p/>
</xsl:when>
<xsl:when test="contains('|p|h1|h2|h3|h4|h5|h6|ul|ol|', concat('|', name(.), '|'))">
<xsl:apply-templates select="." />
</xsl:when>
<xsl:when test="descendant::table|descendant::p|descendant::h1|descendant::h2|descendant::h3|descendant::h4|descendant::h5|descendant::h6|descendant::li">
<xsl:call-template name="block">
<xsl:with-param name="current" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<w:p>
<xsl:call-template name="text-alignment">
<xsl:with-param name="class" select="$class" />
<xsl:with-param name="style" select="$style" />
</xsl:call-template>
<xsl:apply-templates select="." />
</w:p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="tableborders">
<xsl:variable name="border">
<xsl:choose>
<xsl:when test="contains(concat(' ', @class, ' '), ' table-bordered ')">6</xsl:when>
<xsl:when test="not(@border)">0</xsl:when>
<xsl:otherwise><xsl:value-of select="./@border * 6"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="bordertype">
<xsl:choose>
<xsl:when test="$border=0">none</xsl:when>
<xsl:otherwise>single</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<w:tblBorders>
<w:top w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
<w:left w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
<w:bottom w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
<w:right w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
<w:insideH w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
<w:insideV w:val="{$bordertype}" w:sz="{$border}" w:space="0" w:color="auto"/>
</w:tblBorders>
</xsl:template>
<xsl:template name="table-cell-properties">
<w:tcPr>
<xsl:if test="contains(@class, 'ms-border-')">
<w:tcBorders>
<xsl:for-each select="str:tokenize(@class, ' ')">
<xsl:call-template name="define-border">
<xsl:with-param name="class" select="." />
</xsl:call-template>
</xsl:for-each>
</w:tcBorders>
</xsl:if>
<xsl:if test="contains(@class, 'ms-fill-')">
<xsl:variable name="cell-bg" select="str:tokenize(substring-after(@class, 'ms-fill-'), ' ')[1]"/>
<w:shd w:val="clear" w:color="auto" w:fill="{$cell-bg}" />
</xsl:if>
<xsl:if test="@colspan > 1">
<w:gridSpan w:val="{@colspan}"/>
</xsl:if>
</w:tcPr>
</xsl:template>
<xsl:template name="define-border">
<xsl:param name="class" />
<xsl:if test="contains($class, 'ms-border-')">
<xsl:variable name="border" select="substring-after($class, 'ms-border-')"/>
<xsl:variable name="border-properties" select="str:tokenize($border, '-')"/>
<xsl:variable name="border-location" select="$border-properties[1]" />
<xsl:variable name="border-value" select="$border-properties[2]" />
<xsl:variable name="border-color">
<xsl:choose>
<xsl:when test="string-length($border-properties[3]) > 0"><xsl:value-of select="$border-properties[3]"/></xsl:when>
<xsl:otherwise>000000</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="border-size">
<xsl:choose>
<xsl:when test="string-length($border-properties[4]) > 0"><xsl:value-of select="$border-properties[4] * 6"/></xsl:when>
<xsl:otherwise>6</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="w:{$border-location}">
<xsl:attribute name="w:val"><xsl:value-of select="$border-value" /></xsl:attribute>
<xsl:attribute name="w:sz"><xsl:value-of select="$border-size" /></xsl:attribute>
<xsl:attribute name="w:space">0</xsl:attribute>
<xsl:attribute name="w:color"><xsl:value-of select="$border-color" /></xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
================================================
FILE: lib/htmltoword.rb
================================================
# encoding: UTF-8
require 'nokogiri'
require 'zip'
require 'open-uri'
require_relative 'htmltoword/configuration'
module Htmltoword
class << self
def configure
yield configuration
end
def configuration
@configuration ||= Configuration.new
end
alias_method :config, :configuration
end
end
require_relative 'htmltoword/version'
require_relative 'htmltoword/helpers/templates_helper'
require_relative 'htmltoword/helpers/xslt_helper'
require_relative 'htmltoword/document'
if defined?(Rails)
require_relative 'htmltoword/renderer'
require_relative 'htmltoword/railtie'
end
================================================
FILE: script/build-template
================================================
#!/bin/sh
set -e
cwd=$(pwd)
path="$(pwd)/lib/htmltoword/templates/default.docx"
rm -f $path
cd templates/default
# Zip options:
# r - recursive
# l - convert LF to CR LF line endings
# D - Don't make entries for directories
# T - test the resulting zip
# 9 - Moar compression
# q - quiet
# o - make the file as old as the latest entry
zip -r -l -D -T -9 -q -o $path *
cd $cwd
================================================
FILE: script/extract-template
================================================
#!/bin/sh
set -e
rm -rf templates/default
unzip lib/htmltoword/templates/default.docx -d templates/default
================================================
FILE: script/setup
================================================
#!/usr/bin/env sh
if ! which xmllint &>/dev/null; then
echo "Please install xmllint"
exit 0
fi
for f in clean smudge; do
if ! git config --get "filter.xml-c14n.$f" &>/dev/null; then
git config --add "filter.xml-c14n.$f" "xmllint --c14n11 -"
fi
done
================================================
FILE: spec/document_spec.rb
================================================
require 'spec_helper'
require 'securerandom'
describe Htmltoword::Document do
describe "local_images" do
let(:html) do
<<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<img src="https://placehold.it/50x50.png" style="width:50px;height:50px">
<a href="http://www.example.com">
<img src="https://placehold.it/10x10.png" style="width:10px;height:10px">
Hello!
</a>
<p><img src="https://placehold.it/350x150.png" style="width:350px;height:150px"></p>
<p><img src="https://placehold.it/400x250.jpg" style="width:400px;height:250px"></p>
<p><img src="https://placehold.it/350x150.tiff" style="width:350px;height:150px"></p>
<p><img src="https://placehold.it/400x250.gif" style="width:400px;height:250px"></p>
</body>
</html>
EOL
end
#in order to test if the images files are embedded correctly we have to create_and_save, then open the zip and look for them. Then ensure that we cleanup the created file.
#There is probably a better way of doing it as this seems very performance heavy but does have the advantage of testing the create method all the way through...
it "should only embed local images" do
filename = SecureRandom.urlsafe_base64
begin
docx = Htmltoword::Document.create_and_save(html, tmp_path(filename))
Zip::File.open(tmp_path(filename)) do |zip_file|
# Find specific entry
expect(zip_file.glob('word/media/*').size).to eq 6
end
ensure
File.delete(tmp_path(filename))
end
end
end
end
================================================
FILE: spec/fixtures/complex/nestings.html
================================================
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="delivery" data-assembly-id="4" data-marginalia="null">
<div id="content">
<div class="page">
<h1>My document</h1>
<h2>Fake TOC</h2>
<ul>
<li>
<a href="#5">Section 1</a>
(Sec1)
</li>
<li>
<a href="#4384">Section 2</a>
(Sec2)
</li>
</ul>
</div>
<div class="page -page-break">
<div class="assembly-item" id="5">
<div class="document" data-id="7" data-name="name1">
<div class="maincontent" id="name1">
<h1 class="ArtikelATitel">Section 1</h1>
<p class="KildeAarNr">
<a href="#name1" title="Title" shape="rect">Link</a>
</p>
<p class="Forfattere">By Author</p>
<p class="Resume">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. </p>
<div class="toc-sect2" title="Title">
<h1 class="R2">1. Sect</h1>
</div>
<p class="Body">Etiam convallis ut felis a cursus. <a href="/some/route/" targetdocid="docid" title="Title" rel="1" shape="rect" data-idref="idref">link 1 </a>and <a href="/some/route/" targetdocid="docid" title="Title" rel="1" shape="rect" data-idref="idref">28</a>, idet aktier </p>
<h2 class="R3">title 2</h2>
<p class="Body-start">Lorem ipsum dolor sit amet, consectetur adipiscing elit. :<sup class="FootnoteRef"><a href="#name1_NOTE1" shape="rect">[1]</a></sup>
</p>
<table class="realtable" width="100%" cellpadding="2" cellspacing="1">
<tbody>
<tr class="realtable" valign="bottom">
<td class="realtable" rowspan="1" colspan="1">
<p class="Tabelhoved">1,1</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Tabelhoved">1,2</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Tabelhoved">1,3</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">
<sub>=</sub>
<sub>1,4</sub>
</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Tabelhoved">1,5</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Tabelhoved">1,6</p>
</td>
</tr>
<tr class="realtable" valign="top">
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">100</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">100</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">Text</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">Lorem</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">ipsum</p>
</td>
<td class="realtable" rowspan="1" colspan="1">
<p class="Body-start">bla</p>
</td>
</tr>
</tbody>
</table>
<p class="Body-start">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. <img src="http://placehold.it/150x150" data-width="150px" data-height="150px" data-filename="what-a-nice-pic.png" alt="Something beautiful"></p>
<table width="100%" class="list">
<tbody>
<tr class="item">
<td class="itemnum" width="4%" rowspan="1" colspan="1">
<p class="Body">–</p>
</td>
<td class="itembody" width="96%" rowspan="1" colspan="1">
<p>
<span class="style7">1.</span>
<span class="style13">Funny spans </span>
<a href="/some/route/" targetdocid="docid" title="Title" rel="1" shape="rect" data-idref="idref">and links</a>, in <span class="style7">,</span>
<span class="style14"> here </span>
</p>
</td>
</tr>
<tr class="item">
<td class="itemnum" width="4%" rowspan="1" colspan="1">
<p class="Body">–</p>
</td>
<td class="itembody" width="96%" rowspan="1" colspan="1">
<p class="Body">Table list</p>
</td>
</tr>
<tr class="item">
<td class="itemnum" width="4%" rowspan="1" colspan="1">
<p class="Body">–</p>
</td>
<td class="itembody" width="96%" rowspan="1" colspan="1">
<p>With a p and no class<span class="style22">*</span></p>
</td>
</tr>
</tbody>
</table>
<p class="Body-start">Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis.</p>
<p class="Body">Sed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget.</p>
<p class="R6">Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae,</p>
<div class="toc-sect2" title="Title">
<h1 class="R2">2. Div h1</h1>
</div>
<p class="Body-start">lobortis nec dui. Aenean rutrum elementum nulla, ut consequat velit accumsan vitae. Duis iaculis nulla elit, quis rhoncus mi malesuada vel.</p>
<h1 class="footnote-header">Noter</h1>
</div>
</div>
</div>
<hr>
</div>
<div class="page -page-break">
<div class="assembly-item" id="4384">
<div class="document" data-id="706" data-name="name3">
<div class="maincontent" id="name3">
<h1>Section 2</h1>
<div class="toc-sect2" title="Title">
<div id="id">
</div>
<img src="https://placehold.it/250x100.png" style="width:250px; height:100px" alt="Placeholder Image"/>
<h2>Sec 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus </p>
<p> • Fake item 1. Beløbet skal være indbetalt til den finansielle virksomhed</p>
<p> • Fake item 2, long one. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. Sed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget. Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae, lobortis nec dui. Aenean rutrum elementum nulla, ut consequat velit accumsan vitae. Duis iaculis nulla elit, quis rhoncus mi malesuada vel.</p>
<p>
<i class="style2">“… Quoted text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. …”.</i>
</p>
</div>
<hr>
<div class="" id="ftn1">
<p class="ftn">
<a class="ftn" href="/some/route/" name="_ftn1" shape="rect">
<sup><span><span><span>[1]</span></span></span></sup>
</a>
<span>Jf. <a href="/some/route/" title="Title" shape="rect" data-idref="idref">Ref 1</a> lorem ipsum, and <a href="/some/route/" title="Title" shape="rect" data-idref="idref">Ref 2</a> Lorem ipsum dolor sit amet, consectetur adipiscing <i>Italics</i>: elit. Etiam convallis ut felis <i>a cursus</i>: Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. <a href="/some/route/" title="Title" shape="rect" data-idref="idref">Ref 3</a> ed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget. </span>
</p>
<p class="ftn">
<span> </span>
</p>
</div>
<div class="" id="ftn2">
<p class="ftn">
<a href="/some/route/" name="_ftn2" shape="rect">
<sup><span><span><span>[2]</span></span></span></sup>
</a>
<span>Jf. <a href="/some/route/" title="Title" shape="rect" data-idref="idref">Ref 4</a> Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae, lobortis nec dui</span>
</p>
<p class="ftn">
<span> </span>
</p>
</div>
</div>
</div>
</div>
<hr>
</div>
</div>
</div>
</body>
</html>
================================================
FILE: spec/fixtures/complex/nestings.xml
================================================
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">My document</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Fake TOC</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Section 1</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> (Sec1) </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Section 2</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> (Sec2) </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:br w:type="page"/>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Section 1</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Link</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">By Author</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">1. Sect</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Etiam convallis ut felis a cursus. </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">link 1 </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">and </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">28</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">, idet aktier </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">title 2</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. :</w:t>
</w:r>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
<w:t xml:space="preserve">[1]</w:t>
</w:r>
</w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1,1</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1,2</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1,3</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:rPr>
<w:vertAlign w:val="subscript"/>
</w:rPr>
<w:t xml:space="preserve">=</w:t>
</w:r>
<w:r>
<w:rPr>
<w:vertAlign w:val="subscript"/>
</w:rPr>
<w:t xml:space="preserve">1,4</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1,5</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1,6</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">100</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">100</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Text</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">ipsum</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">bla</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. </w:t>
</w:r>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="1524000" cy="1524000"/>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr id="1" name="Picture 1"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic>
<pic:nvPicPr>
<pic:cNvPr id="1" title="Something beautiful" name="what-a-nice-pic.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId8">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="1524000" cy="1524000"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
</w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">–</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">1.</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Funny spans </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">and links</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">, in </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">,</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> here </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">–</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Table list</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">–</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">With a p and no class</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">*</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
<w:p>
<w:r>
<w:t xml:space="preserve">Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Sed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae,</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">2. Div h1</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">lobortis nec dui. Aenean rutrum elementum nulla, ut consequat velit accumsan vitae. Duis iaculis nulla elit, quis rhoncus mi malesuada vel.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Noter</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:br w:type="page"/>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Section 2</w:t>
</w:r>
</w:p>
<w:p/>
<w:drawing>
<wp:inline distT="0" distB="0" distL="0" distR="0">
<wp:extent cx="2540000" cy="1016000"/>
<wp:effectExtent l="0" t="0" r="0" b="0"/>
<wp:docPr id="2" name="Picture 2"/>
<wp:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1"/>
</wp:cNvGraphicFramePr>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
<pic:pic>
<pic:nvPicPr>
<pic:cNvPr id="2" title="Placeholder Image" name="250x100.png"/>
<pic:cNvPicPr/>
</pic:nvPicPr>
<pic:blipFill>
<a:blip r:embed="rId9">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>
<pic:spPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="2540000" cy="1016000"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</pic:spPr>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Sec 2</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> • Fake item 1. Beløbet skal være indbetalt til den finansielle virksomhed</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> • Fake item 2, long one. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. Sed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget. Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae, lobortis nec dui. Aenean rutrum elementum nulla, ut consequat velit accumsan vitae. Duis iaculis nulla elit, quis rhoncus mi malesuada vel.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:i/>
</w:rPr>
<w:t xml:space="preserve">“… Quoted text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam convallis ut felis a cursus. …”.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
<w:t xml:space="preserve">[1]</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Jf. </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Ref 1</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> lorem ipsum, and </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Ref 2</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum dolor sit amet, consectetur adipiscing </w:t>
</w:r>
<w:r>
<w:rPr>
<w:i/>
</w:rPr>
<w:t xml:space="preserve">Italics</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">: elit. Etiam convallis ut felis </w:t>
</w:r>
<w:r>
<w:rPr>
<w:i/>
</w:rPr>
<w:t xml:space="preserve">a cursus</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">: Etiam sodales quis nisl ac elementum. Suspendisse egestas hendrerit diam sit amet mattis. </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Ref 3</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> ed id consectetur orci. Phasellus ultrices laoreet lectus, a laoreet magna accumsan eget. </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
<w:t xml:space="preserve">[2]</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Jf. </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">Ref 4</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> Curabitur erat mi, congue non turpis non, faucibus dapibus magna. Phasellus a accumsan tortor. Quisque quam purus, vehicula a auctor vitae, lobortis nec dui</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
================================================
FILE: spec/fixtures/description_lists/test01.html
================================================
<!doctype html>
<html>
<head></head>
<body>
<!-- Single term and description -->
<dl>
<dt>Firefox</dt>
<dd>
A free, open source, cross-platform,
graphical web browser developed by the
Mozilla Corporation and hundreds of
volunteers.
</dd>
</dl>
</body>
</html>
================================================
FILE: spec/fixtures/description_lists/test01.xml
================================================
<w:p>
<w:r>
<w:t xml:space="preserve">Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">A free, open source, cross-platform, graphical web browser developed by the Mozilla Corporation and hundreds of volunteers. </w:t>
</w:r>
</w:p>
================================================
FILE: spec/fixtures/description_lists/test02.html
================================================
<!doctype html>
<html>
<head></head>
<body>
<!-- Multiple terms, single description -->
<dl>
<dt>Firefox</dt>
<dt>Mozilla Firefox</dt>
<dt>Fx</dt>
<dd>
A free, open source, cross-platform,
graphical web browser developed by the
Mozilla Corporation and hundreds of
volunteers.
</dd>
</dl>
</body>
</html>
================================================
FILE: spec/fixtures/description_lists/test02.xml
================================================
<w:p>
<w:r>
<w:t xml:space="preserve">Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Mozilla Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Fx</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">A free, open source, cross-platform, graphical web browser developed by the Mozilla Corporation and hundreds of volunteers. </w:t>
</w:r>
</w:p>
================================================
FILE: spec/fixtures/description_lists/test03.html
================================================
<!doctype html>
<html>
<head></head>
<body>
<!-- Single term, multiple descriptions -->
<dl>
<dt>Firefox</dt>
<dd>
A free, open source, cross-platform,
graphical web browser developed by the
Mozilla Corporation and hundreds of
volunteers.
</dd>
<dd>
The Red Panda also known as the Lesser
Panda, Wah, Bear Cat or Firefox, is a
mostly herbivorous mammal, slightly larger
than a domestic cat (60 cm long).
</dd>
</dl>
</body>
</html>
================================================
FILE: spec/fixtures/description_lists/test03.xml
================================================
<w:p>
<w:r>
<w:t xml:space="preserve">Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">A free, open source, cross-platform, graphical web browser developed by the Mozilla Corporation and hundreds of volunteers.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">The Red Panda also known as the Lesser Panda, Wah, Bear Cat or Firefox, is a mostly herbivorous mammal, slightly larger than a domestic cat (60 cm long).</w:t>
</w:r>
</w:p>
================================================
FILE: spec/fixtures/description_lists/test04.html
================================================
<!doctype html>
<html>
<head></head>
<body>
<div id="test-container">
<h1>Heading</h1>
Some text
<div>
<dl>
<dt>Firefox</dt>
<dt>Mozilla Firefox</dt>
<dt>Fx</dt>
<dd>
A free, open source, cross-platform,
graphical web browser developed by the
Mozilla Corporation and hundreds of
volunteers.
</dd>
<dd>
The Red Panda also known as the Lesser
Panda, Wah, Bear Cat or Firefox, is a
mostly herbivorous mammal, slightly larger
than a domestic cat (60 cm long).
</dd>
</dl>
</div>
</div>
</body>
</html>
================================================
FILE: spec/fixtures/description_lists/test04.xml
================================================
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Heading</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Some text</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Mozilla Firefox</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Fx</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">A free, open source, cross-platform, graphical web browser developed by the Mozilla Corporation and hundreds of volunteers.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">The Red Panda also known as the Lesser Panda, Wah, Bear Cat or Firefox, is a mostly herbivorous mammal, slightly larger than a domestic cat (60 cm long).</w:t>
</w:r>
</w:p>
================================================
FILE: spec/fixtures/lists/lists_inline_elements.html
================================================
<!DOCTYPE html>
<html>
<head></head>
<body>
<ul>
<li>Some text <span> in a span </span> and some more text
<br>
<div>Text in a new line in div</div>
</li>
<li>Some text (<a href="#link"> link </a>) and some more text
<br>
<div>Text in a new line in div</div>
</li>
<li> Some text <small>in small</small> and again normal</li>
<li> Some text <strong>in strong</strong> and again normal
<br>
<p>New paragraph</p>
</li>
<li>Some text <em>in em</em> and normal text
<br>
<p>New paragraph</p>
</li>
<li>Some text <i>in italics</i> and normal text
<br>
<p>New paragraph</p>
</li>
<li>Some text <b>in bold</b> and normal text
<br>
<p>New paragraph</p>
</li>
<li>Some text <u>underlined</u> and normal text
<br>
<p>New paragraph</p>
</li>
</ul>
</body>
</html>
================================================
FILE: spec/fixtures/lists/lists_inline_elements.xml
================================================
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> in a span </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and some more text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text in a new line in div</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text (</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> link </w:t>
</w:r>
<w:r>
<w:t xml:space="preserve">) and some more text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text in a new line in div</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> Some text in small and again normal</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> Some text </w:t>
</w:r>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">in strong</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and again normal </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">New paragraph</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
<w:r>
<w:rPr>
<w:i/>
</w:rPr>
<w:t xml:space="preserve">in em</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and normal text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">New paragraph</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
<w:r>
<w:rPr>
<w:i/>
</w:rPr>
<w:t xml:space="preserve">in italics</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and normal text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">New paragraph</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">in bold</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and normal text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">New paragraph</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
<w:r>
<w:rPr>
<w:u w:val="single"/>
</w:rPr>
<w:t xml:space="preserve">underlined</w:t>
</w:r>
<w:r>
<w:t xml:space="preserve"> and normal text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">New paragraph</w:t>
</w:r>
</w:p>
================================================
FILE: spec/spec_helper.rb
================================================
require 'rubygems'
require 'bundler/setup'
require 'htmltoword'
include Htmltoword::XSLTHelper
include Htmltoword::TemplatesHelper
def compare_transformed_files(test:, test_file_name:, extras: false)
source = File.read(fixture_path(test, test_file_name, :html), encoding: 'utf-8')
expected_content = File.read(fixture_path(test, test_file_name, :xml), encoding: 'utf-8')
compare_resulting_wordml_with_expected(source, expected_content, extras: extras)
end
def compare_resulting_wordml_with_expected(html, resulting_wordml, extras: false)
source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
result = Htmltoword::Document.new(template_file(nil)).transform_doc_xml(source, extras)
result.gsub!(/\s*<!--(.*?)-->\s*/m, '')
result = remove_declaration(result)
expect(remove_whitespace(result)).to eq(remove_whitespace(resulting_wordml))
end
def compare_numbering_xml(html, expected_xml)
source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
stylesheet = xslt(stylesheet_name: 'numbering')
result = stylesheet.transform(source)
result.xpath('//comment()').remove
result = remove_declaration(result.to_s)
expect(remove_whitespace(result.to_s)).to eq(remove_whitespace(expected_xml))
end
def compare_relations_xml(html, expected_xml)
source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
stylesheet = xslt(stylesheet_name: 'relations')
result = stylesheet.transform(source)
result.xpath('//comment()').remove
result = remove_declaration(result.to_s)
expect(remove_whitespace(result.to_s)).to eq(remove_whitespace(expected_xml))
end
def check_link_text(html, resulting_wordml, extras: false)
source = Nokogiri::HTML(html.gsub(/>\s+</, '><'))
result = Htmltoword::Document.new(template_file(nil)).transform_doc_xml(source, extras)
result.gsub!(/\s*<!--(.*?)-->\s*/m, '')
result = remove_declaration(result)
expect(remove_whitespace_for_link_check(result)).to eq(remove_whitespace_for_link_check(resulting_wordml))
end
private
def fixture_path(folder, file_name, extension)
File.join(File.dirname(__FILE__), 'fixtures', folder, "#{file_name}.#{extension}")
end
#used to temporarily save documents for testing
def tmp_path(filename)
File.join(File.dirname(__FILE__), 'tmp', "#{filename}.docx")
end
def compare_content_of_body?(wordml)
wordml !~ /<?xml version/
end
def remove_whitespace(wordml)
wordml.gsub(/\s+/, ' ').gsub(/(?<keep>>)\s+|\s+(?<keep><)/, '\k<keep>').strip
end
def remove_whitespace_for_link_check(wordml)
wordml.gsub(/^\s+/, '')
end
def remove_declaration(wordml)
wordml.sub(/<\?xml (.*?)>/, '').gsub(/\s*xmlns:(\w+)="(.*?)\s*"/, '')
end
================================================
FILE: spec/tmp/.gitignore
================================================
*
!.gitignore
================================================
FILE: spec/xslt_alignment_spec.rb
================================================
require 'spec_helper'
describe "XSLT to align div, p and td tags" do
it "transforms a p element with the correct alignment." do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<p style="text-align:center;width:100%"> p using text-aligned center</p>
<p style="text-align:right;width:100%"> p using text-aligned right</p>
<p style="text-align:left;width:100%"> p using text-aligned left</p>
<p style="text-align:justify;width:100%">
Praesent commodo leo et tincidunt tincidunt. Aliquam vestibulum vehicula accumsan. In suscipit nunc vitae facilisis mattis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin fringilla, odio in rhoncus tincidunt, mauris lectus gravida nibh, ac consectetur est arcu a turpis. Proin sodales tellus imperdiet, auctor ante sed, pulvinar nisl. Aenean ultricies elementum leo, in mattis dolor dapibus feugiat. Nunc scelerisque nec purus ac tempus. Praesent at velit ac ipsum hendrerit auctor. Nam dui nunc, ultrices quis aliquet in, pellentesque quis diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
</p>
<p class='center'><strong>p class center and strong</strong></p>
<p class='right'><strong>p class right and strong</strong></p>
<p class='left'><strong>p class left and strong</strong></p>
<p class="justify">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ornare sem at sapien accumsan, in pellentesque elit consectetur. Mauris quis dui a magna scelerisque ornare. Vivamus scelerisque sollicitudin ante, auctor dictum nunc iaculis sed. Nullam lobortis ligula odio, a dapibus augue malesuada eget. Nam ac justo nunc. Vestibulum tristique diam sit amet ornare maximus. Duis sit amet libero elit. Proin massa nunc, rutrum nec odio et, hendrerit egestas dui. Donec sit amet aliquam libero.
</p>
<p> Just a p </p>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> p using text-aligned center</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> p using text-aligned right</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> p using text-aligned left</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Praesent commodo leo et tincidunt tincidunt. Aliquam vestibulum vehicula accumsan. In suscipit nunc vitae facilisis mattis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin fringilla, odio in rhoncus tincidunt, mauris lectus gravida nibh, ac consectetur est arcu a turpis. Proin sodales tellus imperdiet, auctor ante sed, pulvinar nisl. Aenean ultricies elementum leo, in mattis dolor dapibus feugiat. Nunc scelerisque nec purus ac tempus. Praesent at velit ac ipsum hendrerit auctor. Nam dui nunc, ultrices quis aliquet in, pellentesque quis diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">p class center and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">p class right and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">p class left and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ornare sem at sapien accumsan, in pellentesque elit consectetur. Mauris quis dui a magna scelerisque ornare. Vivamus scelerisque sollicitudin ante, auctor dictum nunc iaculis sed. Nullam lobortis ligula odio, a dapibus augue malesuada eget. Nam ac justo nunc. Vestibulum tristique diam sit amet ornare maximus. Duis sit amet libero elit. Proin massa nunc, rutrum nec odio et, hendrerit egestas dui. Donec sit amet aliquam libero.
</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Just a p </w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms a table having its cells properly aligned" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<table class="table table-bordered">
<thead>
<tr>
<th>Left aligned text</th>
<th>Right aligned text</th>
<th>Center aligned text</th>
<th>Justify aligned text</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">To the left</td>
<td style="text-align: right;">To the right</td>
<td style="text-align: center;">Centered</td>
<td style="text-align: justify;">Justified</td>
</tr>
<tr>
<td class="left">To the left</td>
<td class="right">To the right</td>
<td class="center">Centered</td>
<td class="justify">Justified</td>
</tr>
</tbody>
</table>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="single" w:sz="6" w:space="0" w:color="auto"/>
<w:left w:val="single" w:sz="6" w:space="0" w:color="auto"/>
<w:bottom w:val="single" w:sz="6" w:space="0" w:color="auto"/>
<w:right w:val="single" w:sz="6" w:space="0" w:color="auto"/>
<w:insideH w:val="single" w:sz="6" w:space="0" w:color="auto"/>
<w:insideV w:val="single" w:sz="6" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Left aligned text</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Right aligned text</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Center aligned text</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Justify aligned text</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">To the left</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">To the right</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Centered</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Justified</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">To the left</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">To the right</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Centered</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Justified</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms div element with the correct alignment" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<div style="text-align:center;width:100%"> div using text-aligned center</div>
<div style="text-align:right;width:100%"> div using text-aligned right</div>
<div style="text-align:left;width:100%"> div using text-aligned left</div>
<div style="text-align:justify;width:100%">
Praesent commodo leo et tincidunt tincidunt. Aliquam vestibulum vehicula accumsan. In suscipit nunc vitae facilisis mattis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin fringilla, odio in rhoncus tincidunt, mauris lectus gravida nibh, ac consectetur est arcu a turpis. Proin sodales tellus imperdiet, auctor ante sed, pulvinar nisl. Aenean ultricies elementum leo, in mattis dolor dapibus feugiat. Nunc scelerisque nec purus ac tempus. Praesent at velit ac ipsum hendrerit auctor. Nam dui nunc, ultrices quis aliquet in, pellentesque quis diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
</div>
<div class='center'><strong>div class center and strong</strong></div>
<div class='right'><strong>div class right and strong</strong></div>
<div class='left'><strong>div class left and strong</strong></div>
<div class="justify">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ornare sem at sapien accumsan, in pellentesque elit consectetur. Mauris quis dui a magna scelerisque ornare. Vivamus scelerisque sollicitudin ante, auctor dictum nunc iaculis sed. Nullam lobortis ligula odio, a dapibus augue malesuada eget. Nam ac justo nunc. Vestibulum tristique diam sit amet ornare maximus. Duis sit amet libero elit. Proin massa nunc, rutrum nec odio et, hendrerit egestas dui. Donec sit amet aliquam libero.
</div>
<div> Just a div </div>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> div using text-aligned center</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> div using text-aligned right</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> div using text-aligned left</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Praesent commodo leo et tincidunt tincidunt. Aliquam vestibulum vehicula accumsan. In suscipit nunc vitae facilisis mattis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin fringilla, odio in rhoncus tincidunt, mauris lectus gravida nibh, ac consectetur est arcu a turpis. Proin sodales tellus imperdiet, auctor ante sed, pulvinar nisl. Aenean ultricies elementum leo, in mattis dolor dapibus feugiat. Nunc scelerisque nec purus ac tempus. Praesent at velit ac ipsum hendrerit auctor. Nam dui nunc, ultrices quis aliquet in, pellentesque quis diam. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">div class center and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">div class right and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">div class left and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="both"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ornare sem at sapien accumsan, in pellentesque elit consectetur. Mauris quis dui a magna scelerisque ornare. Vivamus scelerisque sollicitudin ante, auctor dictum nunc iaculis sed. Nullam lobortis ligula odio, a dapibus augue malesuada eget. Nam ac justo nunc. Vestibulum tristique diam sit amet ornare maximus. Duis sit amet libero elit. Proin massa nunc, rutrum nec odio et, hendrerit egestas dui. Donec sit amet aliquam libero.
</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Just a div </w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms nested divs with proper alignment" do
# TODO: Known bug, not implemented yet.
# <div class=“center”> Something <div> else </div> </div> -> else won’t be centered.
end
it "transforms articles with proper alignment" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<article style="text-align:center;"> article using text-aligned center</article>
<article style="text-align:right;"> article using text-aligned right</article>
<article class='left'><strong>article class left and strong</strong></article>
<article> Just an article </article>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> article using text-aligned center</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> article using text-aligned right</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">article class left and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Just an article </w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms sections with proper alignment" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<section style="text-align:center;"> section using text-aligned center</section>
<section style="text-align:right;"> section using text-aligned right</section>
<section class='left'><strong>section class left and strong</strong></section>
<section> Just an section </section>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> section using text-aligned center</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> section using text-aligned right</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="left"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">section class left and strong</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Just an section </w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
end
================================================
FILE: spec/xslt_breaks_spec.rb
================================================
require 'spec_helper'
describe "XSLT to align div, p and td tags" do
it "transforms br tags children of document body" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<p>Paragraph 1</p>
<br>
<p>Paragraph 2</p>
<div>Paragraph 3</div>
<br>
<div>Paragraph 4</div>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:r>
<w:t xml:space="preserve">Paragraph 1</w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Paragraph 2</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Paragraph 3</w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Paragraph 4</w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms br tags inside a br or p" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<div>
<br>
<div> Lorem ipsum 1 </div>
<br>
<p> Lorem ipsum 2 <br> Lorem ipsum 3 </p>
<div> Lorem ipsum 4 <br> Lorem ipsum 5 </div>
</div>
<div> Lorem ipsum 6 <br> Lorem ipsum 7 </div>
<p> Lorem ipsum 6 <br> Lorem ipsum 7 </p>
<div>
<br>
<p>Lorem ipsum 8</p>
<br>
<p>Lorem ipsum 9 <br> Lorem ipsum 10</p>
</div>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 1 </w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 2 </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 3 </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 4 </w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 5 </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 6 </w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 7 </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 6 </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 7 </w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum 8</w:t>
</w:r>
</w:p>
<w:p>
<w:r/>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum 9 </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum 10</w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms br tags inside lists" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<ol>
<li>Text <br> new line</li>
<li><div>Text inside div <br> new line</div></li>
<li><p>Text inside p <br> new line</p></li>
<li>Some text
<br>
<div>Text in div</div>
</li>
</ol>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text inside div </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text inside p </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text in div</w:t>
</w:r>
</w:p>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it "transforms br tags inside table cells" do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<table>
<tbody>
<tr>
<td><div>Inside a div <br> in a cell</div></td>
<td>Inside a cell <br> no div</td>
<td>
<ul>
<li>Text <br> new line</li>
<li><div>Text inside div <br> new line</div></li>
<li><p>Text inside p <br> new line</p></li>
</ul>
</td>
<td>Some text
<br>
<p>Text inside p</p>
</td>
</tr>
</tbody>
</table>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Inside a div </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> in a cell</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Inside a cell </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:br/>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve"> no div</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
</w:pPr>
<w:r/>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="0"/>
</w:numPr>
<w:ind w:left="720"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text inside div </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Text inside p </w:t>
</w:r>
<w:r>
<w:br/>
</w:r>
<w:r>
<w:t xml:space="preserve"> new line</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Some text </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:br/>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Text inside p</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
end
================================================
FILE: spec/xslt_complex_spec.rb
================================================
require 'spec_helper'
describe 'Bigger and a bit more complex documents' do
it 'transforms documents with nested tables and normal lists and extra classes' do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>My Document</h1>
<div class="pp-clause pp-prologue notable zoomable" id="PP0040850_PR0040858">
<h2><b class="clause_title">Section 1</b></h2>
<div class="precedent-element ann pactable notable" id="PP0040850_AL0040859">
<h3> </h3>
<b class="clause_title">Subsection 1.1</b>
<div class="ppTextPosition annzone">
<div id="PP_1" class="N4 ann annzone">Lorem</div>
<div id="PP_9" class="N4 ann annzone">Ipsum: # </div>
<div id="PP_10" class="N4 ann annzone">dolor: # </div>
<div id="PP_11" class="N4 ann annzone">sit: # </div>
<div id="PP_12" class="N4 ann annzone">amet: # </div>
<div id="PP_13" class="N4 ann annzone">consectetur: # </div>
<div id="PP_14" class="N4 ann annzone">adipiscing: # </div>
<div id="PP_2" class="N4 ann annzone">elit</div>
<div id="PP_3" class="N4 ann annzone">NULLAM AMET</div>
</div>
</div>
</div>
<div class="pp-clause ann notable zoomable" id="PP_55">
<h3><b class="clause_title">Subsection 1.2</b></h3>
<div class="precedent-element ann pactable notable" id="PP_52">
<h4><b class="clause_title">Subsection 1.2.1</b></h4>
<div class="ppTextPosition annzone">
<div id="PP_74" class="N4 ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam amet.</div>
<div id="PP_75" class="N4 ann annzone">
<table class="table-frame-none" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<table class="table-contents" cellpadding="4" cellspacing="0" width="100%">
<colgroup>
<col width="44.5%">
<col width="55.5%">
</colgroup>
<tbody>
<tr>
<td class="valign-cell-top" valign="top"><div class="annzone">Lorem </div></td>
<td class="valign-cell-top" valign="top"><div class="annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. Quisque luctus amet. </div></td>
</tr>
<tr>
<td class="valign-cell-top" valign="top"><div class="annzone">Fake list</div></td>
<td class="valign-cell-top" valign="top"><div class="annzone">(a) Lorem ipsum dolor sit amet, consectetur posuere. </div></td>
</tr>
<tr>
<td class="valign-cell-top" valign="top"><div class="annzone"> </div></td>
<td class="valign-cell-top" valign="top"><div class="annzone">(b) Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. </div></td>
</tr>
<tr>
<td class="valign-cell-top" valign="top"><div class="annzone"> </div></td>
<td class="valign-cell-top" valign="top"><div class="annzone">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehic </div></td>
</tr>
<tr>
<td class="valign-cell-top" valign="top"><div class="annzone">List</div></td>
<td class="valign-cell-top" valign="top">
<ul class="list-style-lower-alpha">
<li> Lorem ipsum </li>
<li> dolor sit amet, </li>
<li> consectetur adipiscing elit </li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="pp-clause ann notable zoomable" id="PP_63">
<h3> </h3>
<b class="clause_title">Nullam ipsum in magna</b>
<div class="precedent-element ann pactable notable" id="PP_65">
<h3> </h3>
<b class="clause_title">Consectetus adipiscing elit.</b>
<div class="ppTextPosition annzone">
<div id="PP_14" class="N4 ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. Quisque luctus amet.</div>
<div id="PP_15" class="N4 ann annzone">
<div class="listbody">
<ul class="manuell">
<li id="PP_16" class="ann annzone">(a) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi.</li>
<li id="PP_17" class="ann annzone">(b) Lorem ipsum dolor sit amet</li>
<li id="PP_18" class="ann annzone">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
</ul>
</div>
</div>
<div id="PP_19" class="N4 ann annzone">Nullam in magna ut nulla efficitur scelerisque. </div>
<div id="PP_20" class="N4 ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi.</div>
<div id="PP_21" class="N4 ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque. Sed scelerisque, ante ac fringilla porta, mi ipsum rhoncus amet.</div>
<div id="PP_22" class="N4 ann annzone">Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque.</div>
</div>
</div>
</div>
<div class="pp-clause ann notable zoomable" id="PP_83">
<h3> </h3>
<b class="clause_title">æåø</b>
<div class="precedent-element ann pactable notable" id="PP_85">
<h3> </h3>
<b class="clause_title">ÁÑÇ ÉÍóü</b>
<div class="ppTextPosition annzone">
<div id="PP_39" class="N4 ann annzone">Œ Æ </div>
<div id="PP_40" class="N4 ann annzone">
<div class="listbody">
<ul class="manuell">
<li id="PP_41" class="ann annzone">(a) Lorem ipsum dolor sit amet</li>
<li id="PP_42" class="ann annzone">(b) Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li>
<li id="PP_43" class="ann annzone">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque. Sed scelerisque, ante ac fringilla porta, mi ipsum rhoncus amet.</li>
<li id="PP_44" class="ann annzone">(d) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi. Vivamus sed id.</li>
<li id="PP_45" class="ann annzone">(e) Vivamus sed id.</li>
<li id="PP_46" class="ann annzone">(f) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi.</li>
<li id="PP_47" class="ann annzone">(g) Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi. Vivamus sed id.</li>
</ul>
</div>
</div>
<div id="PP_59" class="N4 ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa.</div>
</div>
</div>
</div>
<div class="pp-clause ann notable zoomable" id="PP_78">
<h3><b class="clause_title">Clause</b></h3>
<div class="precedent-element ann pactable notable" id="PP_79">
<h3><b class="clause_title">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</b></h3>
<div class="ppTextPosition annzone">
<div id="PP_37" class="N4 ann annzone">Låneavtal # svenska kronor daterat den # 20#</div>
<div id="PP_38" class="N4 ann annzone">1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc suscipit gravida arcu, quis auctor turpis.</div>
<div id="PP_39" class="N4 ann annzone">2. Lorem ipsum dolor sit amet, consectetur adipiscing elit. [Nunc suscipit gravida arcu].</div>
<div id="PP_40" class="N4 ann annzone">3. Datum: #</div>
<div id="PP_41" class="N4 ann annzone">4. Lorem ipsum dolor sit amet #</div>
<div id="PP_42" class="N4 ann annzone">5. Nunc suscipit:
<div class="listbody">
<ul class="manuell">
<li id="PP_43" class="ann annzone">Lorem ipsum dolor sit amet: #</li>
<li id="PP_44" class="ann annzone">Nam volutpat: #</li>
<li id="PP_45" class="ann annzone">Consectetur adipiscing elit. Nam volutpat: #</li>
<li id="PP_46" class="ann annzone">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam volutpat. #</li>
<li id="PP_47" class="ann annzone">Lorem ipsum dolor sit amet, [consectetur]: #</li>
<li id="PP_48" class="ann annzone">[Lorem ipsum] dolor sit amet. Nam volutpat: [ ]</li>
</ul>
</div>
</div>
<div id="PP_50" class="N4 ann annzone">
<table class="table-frame-none" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<table class="table-contents" cellpadding="4" cellspacing="0" width="100%">
<colgroup>
<col width="88%">
</colgroup>
<tbody>
<tr>
<td class="valign-cell-top" valign="top">
<div class="annzone">Place/Date </div>
</td>
</tr>
<tr>
<td class="valign-cell-top" valign="top">
<div class="annzone">______________________ </div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
EOL
expected_wordml = <<-EOL
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">My Document</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Section 1</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Subsection 1.1</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Ipsum: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">dolor: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">sit: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">amet: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">consectetur: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">adipiscing: # </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">elit</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">NULLAM AMET</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Subsection 1.2</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading4"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Subsection 1.2.1</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam amet.</w:t>
</w:r>
</w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem </w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. Quisque luctus amet. </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Fake list</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">(a) Lorem ipsum dolor sit amet, consectetur posuere. </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">(b) Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehic </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">List</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr/>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> Lorem ipsum </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> dolor sit amet, </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> consectetur adipiscing elit </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
<w:p/>
</w:tc>
</w:tr>
</w:tbl>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Nullam ipsum in magna</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Consectetus adipiscing elit.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi. Quisque luctus amet.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(a) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(b) Lorem ipsum dolor sit amet</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Nullam in magna ut nulla efficitur scelerisque. </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce volutpat nunc at nulla scelerisque vehicula. Vestibulum id enim nisi.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque. Sed scelerisque, ante ac fringilla porta, mi ipsum rhoncus amet.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">æåø</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">ÁÑÇ ÉÍóü</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Œ Æ </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(a) Lorem ipsum dolor sit amet</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(b) Lorem ipsum dolor sit amet, consectetur adipiscing elit.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(c) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent aliquam ornare augue. Nullam in magna ut nulla efficitur scelerisque. Sed scelerisque, ante ac fringilla porta, mi ipsum rhoncus amet.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(d) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi. Vivamus sed id.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(e) Vivamus sed id.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(f) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="3"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">(g) Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa. Donec pretium, dui tincidunt vestibulum interdum, dui ex commodo turpis, eget scelerisque orci lacus id mi. Vivamus sed id.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis sit amet arcu augue. Quisque ultricies nec justo a blandit. Sed scelerisque turpis felis. Integer id mauris massa.</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Clause</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3"/>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">Låneavtal # svenska kronor daterat den # 20#</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc suscipit gravida arcu, quis auctor turpis.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">2. Lorem ipsum dolor sit amet, consectetur adipiscing elit. [Nunc suscipit gravida arcu].</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">3. Datum: #</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">4. Lorem ipsum dolor sit amet #</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">5. Nunc suscipit: </w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet: #</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Nam volutpat: #</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Consectetur adipiscing elit. Nam volutpat: #</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam volutpat. #</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Lorem ipsum dolor sit amet, [consectetur]: #</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="4"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">[Lorem ipsum] dolor sit amet. Nam volutpat: [ ]</w:t>
</w:r>
</w:p>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:left w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:bottom w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:right w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideH w:val="none" w:sz="0" w:space="0" w:color="auto"/>
<w:insideV w:val="none" w:sz="0" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="0600" w:firstRow="0" w:lastRow="0" w:firstColumn="0" w:lastColumn="0" w:noHBand="1" w:noVBand="1"/>
</w:tblPr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">Place/Date </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:tcPr/>
<w:p>
<w:r>
<w:t xml:space="preserve">______________________ </w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
<w:p/>
</w:tc>
</w:tr>
</w:tbl>
EOL
compare_resulting_wordml_with_expected(html, expected_wordml.strip)
end
it 'transforms documents with multiple pages and highlight and nested things' do
html = <<-EOL
<!DOCTYPE html>
<html>
<head></head>
<body>
<div class="delivery" data-assembly-id="1" data-marginalia="null">
<div id="content">
<div class="page">
<h1>trial bundle</h1>
<h2>Indholdsfortegnelse</h2>
<ul>
<li>
<a href="#2">Section 1</a>
(Text section)
</li>
<li>
<a href="#37">Section 2</a>
(With highlights)
</li>
<li>
<a href="#43">Section 3</a>
(Highlight only)
</li>
</ul>
</div>
<div class="page -page-break">
<div class="assembly-item" id="2">
<h2>Section 1</h2>
<div class="document" data-id="3" data-name="name1">
<div class="maincontent zoom" id="name1">
<div id="name1_P2" class="P ann clippable zoomable notable alertable">
<h3>§ 2</h3>
<div class="element-body annz
gitextract_jrowts2d/
├── .gitattributes
├── .gitignore
├── CHANGELOG.txt
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin/
│ └── htmltoword
├── docs/
│ ├── styles.md
│ └── supported_elements.md
├── htmltoword.gemspec
├── lib/
│ ├── htmltoword/
│ │ ├── configuration.rb
│ │ ├── document.rb
│ │ ├── helpers/
│ │ │ ├── templates_helper.rb
│ │ │ └── xslt_helper.rb
│ │ ├── railtie.rb
│ │ ├── renderer.rb
│ │ ├── templates/
│ │ │ └── default.docx
│ │ ├── version.rb
│ │ └── xslt/
│ │ ├── base.xslt
│ │ ├── cleanup.xslt
│ │ ├── extras.xslt
│ │ ├── functions.xslt
│ │ ├── htmltoword.xslt
│ │ ├── image_functions.xslt
│ │ ├── images.xslt
│ │ ├── inline_elements.xslt
│ │ ├── links.xslt
│ │ ├── numbering.xslt
│ │ ├── relations.xslt
│ │ ├── style2.xslt
│ │ └── tables.xslt
│ └── htmltoword.rb
├── script/
│ ├── build-template
│ ├── extract-template
│ └── setup
├── spec/
│ ├── document_spec.rb
│ ├── fixtures/
│ │ ├── complex/
│ │ │ ├── nestings.html
│ │ │ └── nestings.xml
│ │ ├── description_lists/
│ │ │ ├── test01.html
│ │ │ ├── test01.xml
│ │ │ ├── test02.html
│ │ │ ├── test02.xml
│ │ │ ├── test03.html
│ │ │ ├── test03.xml
│ │ │ ├── test04.html
│ │ │ └── test04.xml
│ │ └── lists/
│ │ ├── lists_inline_elements.html
│ │ └── lists_inline_elements.xml
│ ├── spec_helper.rb
│ ├── tmp/
│ │ └── .gitignore
│ ├── xslt_alignment_spec.rb
│ ├── xslt_breaks_spec.rb
│ ├── xslt_complex_spec.rb
│ ├── xslt_description_lists_spec.rb
│ ├── xslt_heading_spec.rb
│ ├── xslt_images_spec.rb
│ ├── xslt_links_spec.rb
│ ├── xslt_lists_spec.rb
│ ├── xslt_simple_text_style_spec.rb
│ ├── xslt_spec.rb
│ └── xslt_tables_spec.rb
└── templates/
└── default/
├── [Content_Types].xml
├── _rels/
│ └── .rels
├── docProps/
│ ├── app.xml
│ └── core.xml
└── word/
├── _rels/
│ └── document.xml.rels
├── document.xml
├── fontTable.xml
├── numbering.xml
├── settings.xml
├── styles.xml
├── stylesWithEffects.xml
├── theme/
│ └── theme1.xml
└── webSettings.xml
SYMBOL INDEX (54 symbols across 9 files)
FILE: lib/htmltoword.rb
type Htmltoword (line 7) | module Htmltoword
function configure (line 9) | def configure
function configuration (line 13) | def configuration
FILE: lib/htmltoword/configuration.rb
type Htmltoword (line 1) | module Htmltoword
class Configuration (line 2) | class Configuration
method initialize (line 5) | def initialize
FILE: lib/htmltoword/document.rb
type Htmltoword (line 1) | module Htmltoword
class Document (line 2) | class Document
method create (line 7) | def create(content, template_name = nil, extras = false)
method create_and_save (line 14) | def create_and_save(content, file_path, template_name = nil, extras ...
method create_with_content (line 20) | def create_with_content(template, content, extras = false)
method extension (line 27) | def extension
method doc_xml_file (line 31) | def doc_xml_file
method numbering_xml_file (line 35) | def numbering_xml_file
method relations_xml_file (line 39) | def relations_xml_file
method content_types_xml_file (line 43) | def content_types_xml_file
method initialize (line 48) | def initialize(template_path)
method generate (line 57) | def generate
method replace_files (line 92) | def replace_files(html, extras = false)
method transform_doc_xml (line 102) | def transform_doc_xml(source, extras = false)
method transform_and_replace (line 110) | def transform_and_replace(source, stylesheet_path, file, remove_ns =...
method local_images (line 119) | def local_images(source)
method content_type_from_extension (line 129) | def content_type_from_extension(ext)
method inject_image_content_types (line 134) | def inject_image_content_types(source)
FILE: lib/htmltoword/helpers/templates_helper.rb
type Htmltoword (line 1) | module Htmltoword
type TemplatesHelper (line 2) | module TemplatesHelper
function template_file (line 3) | def template_file(template_file_name = nil)
FILE: lib/htmltoword/helpers/xslt_helper.rb
type Htmltoword (line 1) | module Htmltoword
type XSLTHelper (line 2) | module XSLTHelper
function document_xslt (line 3) | def document_xslt(extras = false)
function xslt_path (line 8) | def xslt_path(template_name)
function xslt (line 12) | def xslt(stylesheet_name: nil, stylesheet_path: nil)
FILE: lib/htmltoword/railtie.rb
type Htmltoword (line 1) | module Htmltoword
class Railtie (line 2) | class Railtie < ::Rails::Railtie
method to_docx (line 14) | def to_docx
FILE: lib/htmltoword/renderer.rb
type Htmltoword (line 1) | module Htmltoword
class Renderer (line 2) | class Renderer
method send_file (line 4) | def send_file(context, filename, options = {})
method initialize (line 9) | def initialize(context, filename, options)
method send_file (line 19) | def send_file
method define_template (line 26) | def define_template(filename, options)
method file_name (line 38) | def file_name(filename, options)
FILE: lib/htmltoword/version.rb
type Htmltoword (line 1) | module Htmltoword
FILE: spec/spec_helper.rb
function compare_transformed_files (line 8) | def compare_transformed_files(test:, test_file_name:, extras: false)
function compare_resulting_wordml_with_expected (line 14) | def compare_resulting_wordml_with_expected(html, resulting_wordml, extra...
function compare_numbering_xml (line 23) | def compare_numbering_xml(html, expected_xml)
function compare_relations_xml (line 32) | def compare_relations_xml(html, expected_xml)
function check_link_text (line 41) | def check_link_text(html, resulting_wordml, extras: false)
function fixture_path (line 51) | def fixture_path(folder, file_name, extension)
function tmp_path (line 56) | def tmp_path(filename)
function compare_content_of_body? (line 60) | def compare_content_of_body?(wordml)
function remove_whitespace (line 64) | def remove_whitespace(wordml)
function remove_whitespace_for_link_check (line 68) | def remove_whitespace_for_link_check(wordml)
function remove_declaration (line 72) | def remove_declaration(wordml)
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (416K chars).
[
{
"path": ".gitattributes",
"chars": 71,
"preview": "templates/**/*.xml filter=xml-c14n\ntemplates/**/*.rels filter=xml-c14n\n"
},
{
"path": ".gitignore",
"chars": 158,
"preview": "*.gem\n*.rbc\n.bundle\n.config\n.yardoc\nGemfile.lock\nInstalledFiles\n_yardoc\ncoverage\ndoc/\nlib/bundler/man\npkg\nrdoc\nspec/repo"
},
{
"path": "CHANGELOG.txt",
"chars": 2997,
"preview": "CHANGELOG\nVersion 0.6.0\n* Improve support for inline elements\n* Add basic support for section and article elements\n\nVers"
},
{
"path": "Gemfile",
"chars": 95,
"preview": "source 'https://rubygems.org'\n\n# Specify your gem's dependencies in htmltoword.gemspec\ngemspec\n"
},
{
"path": "LICENSE.txt",
"chars": 1074,
"preview": "Copyright (c) 2013 Nicholas Frandsen\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "README.md",
"chars": 7377,
"preview": "# Ruby Html to word Gem \n\nThis simple gem allows you to create MS Word docx documents from simple html documents. This m"
},
{
"path": "Rakefile",
"chars": 108,
"preview": "require \"bundler/gem_tasks\"\nrequire 'rspec/core/rake_task'\ntask :default => :spec\nRSpec::Core::RakeTask.new\n"
},
{
"path": "bin/htmltoword",
"chars": 1035,
"preview": "#!/usr/bin/env ruby\nrequire 'methadone'\nrequire 'rmultimarkdown'\nrequire_relative '../lib/htmltoword'\n\ninclude Methadone"
},
{
"path": "docs/styles.md",
"chars": 6346,
"preview": "Courtesy of @fran-worley\n\nThis list is not comprehensive or tested, but I have looked through the source code, and readm"
},
{
"path": "docs/supported_elements.md",
"chars": 3381,
"preview": "# Supported elements \n\n`<Work in progress>`\n\n## Unsupported elements\n\nThe following elements are explicitly not supporte"
},
{
"path": "htmltoword.gemspec",
"chars": 1334,
"preview": "# coding: utf-8\nlib = File.expand_path('../lib', __FILE__)\n$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)\nrequi"
},
{
"path": "lib/htmltoword/configuration.rb",
"chars": 521,
"preview": "module Htmltoword\n class Configuration\n attr_accessor :default_templates_path, :custom_templates_path, :default_xslt"
},
{
"path": "lib/htmltoword/document.rb",
"chars": 5480,
"preview": "module Htmltoword\n class Document\n include XSLTHelper\n\n class << self\n include TemplatesHelper\n def cre"
},
{
"path": "lib/htmltoword/helpers/templates_helper.rb",
"chars": 390,
"preview": "module Htmltoword\n module TemplatesHelper\n def template_file(template_file_name = nil)\n default_path = File.joi"
},
{
"path": "lib/htmltoword/helpers/xslt_helper.rb",
"chars": 491,
"preview": "module Htmltoword\n module XSLTHelper\n def document_xslt(extras = false)\n file_name = extras ? 'htmltoword' : 'b"
},
{
"path": "lib/htmltoword/railtie.rb",
"chars": 765,
"preview": "module Htmltoword\n class Railtie < ::Rails::Railtie\n initializer 'htmltoword.setup' do\n if defined?(Mime) and M"
},
{
"path": "lib/htmltoword/renderer.rb",
"chars": 1302,
"preview": "module Htmltoword\n class Renderer\n class << self\n def send_file(context, filename, options = {})\n new(co"
},
{
"path": "lib/htmltoword/version.rb",
"chars": 42,
"preview": "module Htmltoword\n VERSION = '1.1.1'\nend\n"
},
{
"path": "lib/htmltoword/xslt/base.xslt",
"chars": 17789,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/cleanup.xslt",
"chars": 3322,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:str=\"http://exslt.org/strings\"\n "
},
{
"path": "lib/htmltoword/xslt/extras.xslt",
"chars": 1286,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/functions.xslt",
"chars": 1917,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/htmltoword.xslt",
"chars": 1226,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/image_functions.xslt",
"chars": 6563,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/images.xslt",
"chars": 6927,
"preview": "<xsl:stylesheet xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\"\n xmlns:mo="
},
{
"path": "lib/htmltoword/xslt/inline_elements.xslt",
"chars": 2557,
"preview": "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n <xsl:output encoding=\"utf-8\" omit-xml-"
},
{
"path": "lib/htmltoword/xslt/links.xslt",
"chars": 1690,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/numbering.xslt",
"chars": 9097,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/relations.xslt",
"chars": 3537,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns=\"http://schemas.openxmlformats.or"
},
{
"path": "lib/htmltoword/xslt/style2.xslt",
"chars": 3014,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword/xslt/tables.xslt",
"chars": 7330,
"preview": "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n xmlns:w=\"http://schemas.openxmlformats."
},
{
"path": "lib/htmltoword.rb",
"chars": 615,
"preview": "# encoding: UTF-8\nrequire 'nokogiri'\nrequire 'zip'\nrequire 'open-uri'\nrequire_relative 'htmltoword/configuration'\n\nmodul"
},
{
"path": "script/build-template",
"chars": 380,
"preview": "#!/bin/sh\n\nset -e\n\ncwd=$(pwd)\npath=\"$(pwd)/lib/htmltoword/templates/default.docx\"\nrm -f $path\ncd templates/default\n\n# Zi"
},
{
"path": "script/extract-template",
"chars": 109,
"preview": "#!/bin/sh\n\nset -e\n\nrm -rf templates/default\nunzip lib/htmltoword/templates/default.docx -d templates/default\n"
},
{
"path": "script/setup",
"chars": 262,
"preview": "#!/usr/bin/env sh\nif ! which xmllint &>/dev/null; then\n echo \"Please install xmllint\"\n exit 0\nfi\n\nfor f in clean smudg"
},
{
"path": "spec/document_spec.rb",
"chars": 1657,
"preview": "require 'spec_helper'\nrequire 'securerandom'\n\ndescribe Htmltoword::Document do\n describe \"local_images\" do\n let(:htm"
},
{
"path": "spec/fixtures/complex/nestings.html",
"chars": 9360,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body>\n<div class=\"delivery\" data-assembly-id=\"4\" data-marginalia=\"null\">\n <div i"
},
{
"path": "spec/fixtures/complex/nestings.xml",
"chars": 13031,
"preview": "<w:p>\n <w:pPr>\n <w:pStyle w:val=\"Heading1\"/>\n </w:pPr>\n <w:r>\n <w:t xml:space=\"preserve\">My document</w:t>\n </"
},
{
"path": "spec/fixtures/description_lists/test01.html",
"chars": 282,
"preview": "<!doctype html>\n<html>\n<head></head>\n<body>\n<!-- Single term and description -->\n<dl>\n <dt>Firefox</dt>\n <dd>\n A fr"
},
{
"path": "spec/fixtures/description_lists/test01.xml",
"chars": 312,
"preview": "<w:p>\n <w:r>\n <w:t xml:space=\"preserve\">Firefox</w:t>\n </w:r>\n</w:p>\n<w:p>\n <w:pPr>\n <w:ind w:left=\"720\"/>\n </"
},
{
"path": "spec/fixtures/description_lists/test02.html",
"chars": 330,
"preview": "<!doctype html>\n<html>\n<head></head>\n<body>\n<!-- Multiple terms, single description -->\n<dl>\n <dt>Firefox</dt>\n <dt>Mo"
},
{
"path": "spec/fixtures/description_lists/test02.xml",
"chars": 445,
"preview": "<w:p>\n <w:r>\n <w:t xml:space=\"preserve\">Firefox</w:t>\n </w:r>\n</w:p>\n<w:p>\n<w:r>\n <w:t xml:space=\"preserve\">Mozill"
},
{
"path": "spec/fixtures/description_lists/test03.html",
"chars": 474,
"preview": "<!doctype html>\n<html>\n<head></head>\n<body>\n<!-- Single term, multiple descriptions -->\n<dl>\n <dt>Firefox</dt>\n <dd>\n "
},
{
"path": "spec/fixtures/description_lists/test03.xml",
"chars": 578,
"preview": "<w:p>\n <w:r>\n <w:t xml:space=\"preserve\">Firefox</w:t>\n </w:r>\n</w:p>\n<w:p>\n <w:pPr>\n <w:ind w:left=\"720\"/>\n </"
},
{
"path": "spec/fixtures/description_lists/test04.html",
"chars": 620,
"preview": "<!doctype html>\n<html>\n<head></head>\n<body>\n<div id=\"test-container\">\n <h1>Heading</h1>\n Some text\n <div>\n <dl>\n "
},
{
"path": "spec/fixtures/description_lists/test04.xml",
"chars": 897,
"preview": "<w:p>\n <w:pPr>\n <w:pStyle w:val=\"Heading1\"/>\n </w:pPr>\n <w:r>\n <w:t xml:space=\"preserve\">Heading</w:t>\n </w:r>"
},
{
"path": "spec/fixtures/lists/lists_inline_elements.html",
"chars": 839,
"preview": "<!DOCTYPE html>\n<html>\n<head></head>\n<body>\n<ul>\n <li>Some text <span> in a span </span> and some more text\n <br>\n "
},
{
"path": "spec/fixtures/lists/lists_inline_elements.xml",
"chars": 5342,
"preview": "<w:p>\n <w:pPr>\n <w:pStyle w:val=\"ListParagraph\"/>\n <w:numPr>\n <w:ilvl w:val=\"0\"/>\n <w:numId w:val=\"1\"/>"
},
{
"path": "spec/spec_helper.rb",
"chars": 2608,
"preview": "require 'rubygems'\nrequire 'bundler/setup'\nrequire 'htmltoword'\n\ninclude Htmltoword::XSLTHelper\ninclude Htmltoword::Temp"
},
{
"path": "spec/tmp/.gitignore",
"chars": 14,
"preview": "*\n\n!.gitignore"
},
{
"path": "spec/xslt_alignment_spec.rb",
"chars": 16385,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT to align div, p and td tags\" do\n\n it \"transforms a p element with the correct ali"
},
{
"path": "spec/xslt_breaks_spec.rb",
"chars": 9809,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT to align div, p and td tags\" do\n\n it \"transforms br tags children of document bod"
},
{
"path": "spec/xslt_complex_spec.rb",
"chars": 41023,
"preview": "require 'spec_helper'\n\ndescribe 'Bigger and a bit more complex documents' do\n\n it 'transforms documents with nested tab"
},
{
"path": "spec/xslt_description_lists_spec.rb",
"chars": 857,
"preview": "require 'spec_helper'\n\nRSpec.describe 'XSLT supporting description lists' do\n\n it 'transforms correctly a single term a"
},
{
"path": "spec/xslt_heading_spec.rb",
"chars": 17202,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT for Headings\" do\n\n it \"transforms heading tags in the body\" do\n html = <<-EOL\n"
},
{
"path": "spec/xslt_images_spec.rb",
"chars": 12574,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT to include images\" do\n it \"generates correct image wordml from html\" do\n html "
},
{
"path": "spec/xslt_links_spec.rb",
"chars": 4911,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT for Links\" do\n\n it \"transforms heading tags in a div\" do\n html = <<-EOL\n <!DO"
},
{
"path": "spec/xslt_lists_spec.rb",
"chars": 16282,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT supporting lists\" do\n it \"transforms a simple ol list\" do\n html = <<-EOL\n <!D"
},
{
"path": "spec/xslt_simple_text_style_spec.rb",
"chars": 19940,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT to make text bold or italic\" do\n\n it \"transforms simple b, strong, em and italic "
},
{
"path": "spec/xslt_spec.rb",
"chars": 2914,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT\" do\n\n it \"transforms an empty html doc into an empty docx doc\" do\n html = '<ht"
},
{
"path": "spec/xslt_tables_spec.rb",
"chars": 20046,
"preview": "require 'spec_helper'\n\ndescribe \"XSLT for tables\" do\n\n it \"transforms a table into a tbl element\" do\n html = <<-EOL\n"
},
{
"path": "templates/default/[Content_Types].xml",
"chars": 1969,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/con"
},
{
"path": "templates/default/_rels/.rels",
"chars": 748,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/"
},
{
"path": "templates/default/docProps/app.xml",
"chars": 232,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocum"
},
{
"path": "templates/default/docProps/core.xml",
"chars": 346,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/p"
},
{
"path": "templates/default/word/_rels/document.xml.rels",
"chars": 1108,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/"
},
{
"path": "templates/default/word/document.xml",
"chars": 5305,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:document xmlns:wpc=\"http://schemas.microsoft.com/office/word/"
},
{
"path": "templates/default/word/fontTable.xml",
"chars": 2962,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:fonts xmlns:mc=\"http://schemas.openxmlformats.org/markup-comp"
},
{
"path": "templates/default/word/numbering.xml",
"chars": 8057,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:numbering xmlns:wpc=\"http://schemas.microsoft.com/office/word"
},
{
"path": "templates/default/word/settings.xml",
"chars": 3060,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:settings xmlns:mc=\"http://schemas.openxmlformats.org/markup-c"
},
{
"path": "templates/default/word/styles.xml",
"chars": 25541,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:styles xmlns:mc=\"http://schemas.openxmlformats.org/markup-com"
},
{
"path": "templates/default/word/stylesWithEffects.xml",
"chars": 26407,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:styles xmlns:wpc=\"http://schemas.microsoft.com/office/word/20"
},
{
"path": "templates/default/word/theme/theme1.xml",
"chars": 10879,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<a:theme xmlns:a=\"http://schemas.openxmlformats.org/drawingml/20"
},
{
"path": "templates/default/word/webSettings.xml",
"chars": 438,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:webSettings xmlns:mc=\"http://schemas.openxmlformats.org/marku"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the karnov/htmltoword GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (377.3 KB), approximately 129.8k tokens, and a symbol index with 54 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.