reverse_adoc 0.2.3 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +8 -4
  3. data/.github/workflows/ubuntu.yml +10 -4
  4. data/.github/workflows/windows.yml +12 -5
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +84 -0
  7. data/README.adoc +36 -3
  8. data/bin/reverse_adoc +7 -0
  9. data/bin/w2a +5 -17
  10. data/lib/reverse_asciidoctor.rb +7 -47
  11. data/lib/reverse_asciidoctor/cleaner.rb +23 -0
  12. data/lib/reverse_asciidoctor/config.rb +2 -1
  13. data/lib/reverse_asciidoctor/converters/a.rb +6 -2
  14. data/lib/reverse_asciidoctor/converters/example.rb +17 -0
  15. data/lib/reverse_asciidoctor/converters/express_ref.rb +12 -0
  16. data/lib/reverse_asciidoctor/converters/ext_description.rb +16 -0
  17. data/lib/reverse_asciidoctor/converters/ext_descriptions.rb +12 -0
  18. data/lib/reverse_asciidoctor/converters/h.rb +17 -2
  19. data/lib/reverse_asciidoctor/converters/img.rb +23 -20
  20. data/lib/reverse_asciidoctor/converters/note.rb +17 -0
  21. data/lib/reverse_asciidoctor/html_converter.rb +56 -0
  22. data/lib/reverse_asciidoctor/smrl_description_converter.rb +45 -0
  23. data/lib/reverse_asciidoctor/version.rb +1 -1
  24. data/reverse_adoc.gemspec +1 -0
  25. data/spec/assets/anchors.html +8 -0
  26. data/spec/assets/external_images.docx +0 -0
  27. data/spec/assets/external_images.html +35 -0
  28. data/spec/bin/reverse_adoc_spec.rb +32 -0
  29. data/spec/bin/w2a_spec.rb +35 -0
  30. data/spec/components/anchors_spec.rb +5 -0
  31. data/spec/lib/reverse_asciidoctor/cleaner_spec.rb +24 -0
  32. data/spec/lib/reverse_asciidoctor/converters/example_spec.rb +22 -0
  33. data/spec/lib/reverse_asciidoctor/converters/express_ref_spec.rb +14 -0
  34. data/spec/lib/reverse_asciidoctor/converters/ext_description_spec.rb +20 -0
  35. data/spec/lib/reverse_asciidoctor/converters/ext_descriptions_spec.rb +13 -0
  36. data/spec/lib/reverse_asciidoctor/converters/note_spec.rb +22 -0
  37. data/spec/lib/reverse_asciidoctor_spec.rb +58 -5
  38. data/spec/spec_helper.rb +5 -0
  39. data/spec/support/shell_helpers.rb +15 -0
  40. metadata +45 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8003d7dcf58a0561295e898bbcc93ce2c4f6168f5b9e2bcb17791fc183a48d04
4
- data.tar.gz: 1229e27b2b00ce61d1004bf3348552b8c3749d3b15f0490c3ab85d63bec94964
3
+ metadata.gz: eb34effa1c1af2e72ef8df7b6b1553c7c2574bcca9608e02cfaf561ed8a2bfec
4
+ data.tar.gz: e18b3b9cf2d936a48fdf2e6d5f265aa5c945c9493bd232a4d8fb311df780e81f
5
5
  SHA512:
6
- metadata.gz: 5e162c8c8a83ca274faed8247ff8fde809118e1a2fa02e3cfaf75f1804d9163d6019ee5bd79a33fe3b2dd00aee2780e8809f2139ffbc118899a8985689feedf8
7
- data.tar.gz: d8c715a4ccb49082a832590f89b4b434b1502e1d7c2bcc9539fb0c5b47ddc09afb8b87236a48913ebe8dbecb02f848ffa20d83f9b7f2100bc3ed57355309bb25
6
+ metadata.gz: ca8454b96ad3064c16018f09198f8450f9a15e6525c1df6e63b7a0e3dd3254f66f2bee56e69e8c7088087962911480513f3608c759f955489b2e602dc2251890
7
+ data.tar.gz: 49c2198645f22b9ac26ea78aa36e1073a27807dca8364ad076250dccfc6b307055775894962d70d6400d7c8ec6b3dfa02cb31c84c922c60d8c18cbbf5ee55171
@@ -1,14 +1,18 @@
1
- # Auto-generated !!! Do not edit it manually
2
- # use ci-master https://github.com/metanorma/metanorma-build-scripts
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
3
  name: macos
4
4
 
5
- on: [push]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
6
9
 
7
10
  jobs:
8
11
  test-macos:
9
12
  name: Test on Ruby ${{ matrix.ruby }} macOS
10
13
  runs-on: macos-latest
11
14
  strategy:
15
+ fail-fast: false
12
16
  matrix:
13
17
  ruby: [ '2.6', '2.5', '2.4' ]
14
18
  steps:
@@ -20,7 +24,7 @@ jobs:
20
24
  architecture: 'x64'
21
25
  - name: Update gems
22
26
  run: |
23
- sudo gem install bundler -v "~> 2" --force
27
+ sudo gem install bundler --force
24
28
  bundle install --jobs 4 --retry 3
25
29
  - name: Run specs
26
30
  run: |
@@ -1,14 +1,18 @@
1
- # Auto-generated !!! Do not edit it manually
2
- # use ci-master https://github.com/metanorma/metanorma-build-scripts
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
3
  name: ubuntu
4
4
 
5
- on: [push]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
6
9
 
7
10
  jobs:
8
11
  test-linux:
9
12
  name: Test on Ruby ${{ matrix.ruby }} Ubuntu
10
13
  runs-on: ubuntu-latest
11
14
  strategy:
15
+ fail-fast: false
12
16
  matrix:
13
17
  ruby: [ '2.6', '2.5', '2.4' ]
14
18
  steps:
@@ -18,9 +22,11 @@ jobs:
18
22
  with:
19
23
  ruby-version: ${{ matrix.ruby }}
20
24
  architecture: 'x64'
25
+ - name: Install LibreOffice
26
+ run: sudo apt-get -y --no-install-recommends install libreoffice
21
27
  - name: Update gems
22
28
  run: |
23
- gem install bundler -v "~> 2"
29
+ gem install bundler
24
30
  bundle install --jobs 4 --retry 3
25
31
  - name: Run specs
26
32
  run: |
@@ -1,14 +1,18 @@
1
- # Auto-generated !!! Do not edit it manually
2
- # use ci-master https://github.com/metanorma/metanorma-build-scripts
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
3
  name: windows
4
4
 
5
- on: [push]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
6
9
 
7
10
  jobs:
8
11
  test-windows:
9
12
  name: Test on Ruby ${{ matrix.ruby }} Windows
10
13
  runs-on: windows-latest
11
14
  strategy:
15
+ fail-fast: false
12
16
  matrix:
13
17
  ruby: [ '2.6', '2.5', '2.4' ]
14
18
  steps:
@@ -18,12 +22,15 @@ jobs:
18
22
  with:
19
23
  ruby-version: ${{ matrix.ruby }}
20
24
  architecture: 'x64'
25
+ - name: Install LibreOffice
26
+ run: |
27
+ choco install libreoffice-still
28
+ echo "::add-path::C:\Program Files\LibreOffice\program"
21
29
  - name: Update gems
22
30
  shell: pwsh
23
31
  run: |
24
- gem install bundler -v "~> 2"
32
+ gem install bundler
25
33
  bundle config --local path vendor/bundle
26
- bundle update
27
34
  bundle install --jobs 4 --retry 3
28
35
  - name: Run specs
29
36
  run: |
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source "https://rubygems.org"
2
-
2
+
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in reverse_asciidoctor.gemspec
6
6
  gemspec
7
+
8
+ gem "byebug"
@@ -0,0 +1,84 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ reverse_adoc (0.2.8)
5
+ mathml2asciimath
6
+ mimemagic
7
+ nokogiri (>= 1.10.4)
8
+ word-to-markdown
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.7.0)
14
+ public_suffix (>= 2.0.2, < 5.0)
15
+ byebug (11.1.1)
16
+ cliver (0.3.2)
17
+ codeclimate-test-reporter (1.0.7)
18
+ simplecov
19
+ css_parser (1.7.1)
20
+ addressable
21
+ descriptive_statistics (2.5.1)
22
+ diff-lcs (1.3)
23
+ docile (1.3.2)
24
+ ffi (1.13.1)
25
+ htmlentities (4.3.4)
26
+ mathml2asciimath (0.0.10)
27
+ htmlentities (~> 4.3.4)
28
+ nokogiri (>= 1.10.4)
29
+ mimemagic (0.3.5)
30
+ mini_portile2 (2.4.0)
31
+ nokogiri (1.10.9)
32
+ mini_portile2 (~> 2.4.0)
33
+ nokogiri-styles (0.1.2)
34
+ nokogiri
35
+ premailer (1.11.1)
36
+ addressable
37
+ css_parser (>= 1.6.0)
38
+ htmlentities (>= 4.0.0)
39
+ public_suffix (4.0.5)
40
+ rake (13.0.1)
41
+ redcarpet (3.5.0)
42
+ reverse_markdown (1.4.0)
43
+ nokogiri
44
+ rspec (3.9.0)
45
+ rspec-core (~> 3.9.0)
46
+ rspec-expectations (~> 3.9.0)
47
+ rspec-mocks (~> 3.9.0)
48
+ rspec-core (3.9.1)
49
+ rspec-support (~> 3.9.1)
50
+ rspec-expectations (3.9.0)
51
+ diff-lcs (>= 1.2.0, < 2.0)
52
+ rspec-support (~> 3.9.0)
53
+ rspec-mocks (3.9.1)
54
+ diff-lcs (>= 1.2.0, < 2.0)
55
+ rspec-support (~> 3.9.0)
56
+ rspec-support (3.9.2)
57
+ simplecov (0.18.5)
58
+ docile (~> 1.1)
59
+ simplecov-html (~> 0.11)
60
+ simplecov-html (0.12.1)
61
+ sys-proctable (1.2.5)
62
+ ffi
63
+ word-to-markdown (1.1.8)
64
+ cliver (~> 0.3)
65
+ descriptive_statistics (~> 2.5)
66
+ nokogiri-styles (~> 0.1)
67
+ premailer (~> 1.8)
68
+ reverse_markdown (~> 1.0)
69
+ sys-proctable (~> 1.0)
70
+
71
+ PLATFORMS
72
+ ruby
73
+
74
+ DEPENDENCIES
75
+ byebug
76
+ codeclimate-test-reporter
77
+ rake
78
+ redcarpet
79
+ reverse_adoc!
80
+ rspec
81
+ simplecov
82
+
83
+ BUNDLED WITH
84
+ 2.0.2
@@ -1,9 +1,12 @@
1
1
  = AsciiDoc from HTML and Microsoft Word: reverse_adoc
2
2
 
3
- image:https://img.shields.io/gem/v/reverse_adoc.svg["Gem Version", link="https://rubygems.org/gems/reverse_adoc"]
4
- image:https://img.shields.io/travis/metanorma/reverse_adoc/master.svg["Build Status", link="https://travis-ci.org/metanorma/reverse_adoc"]
3
+ https://github.com/metanorma/reverse_adoc[reverse_adoc] image:https://img.shields.io/gem/v/reverse_adoc.svg["Gem Version", link="https://rubygems.org/gems/reverse_adoc"]::
4
+ image:https://github.com/metanorma/reverse_adoc/workflows/macos/badge.svg["Build Status", link="https://github.com/metanorma/reverse_adoc/actions?workflow=macos"]
5
+ image:https://github.com/metanorma/reverse_adoc/workflows/windows/badge.svg["Build Status", link="https://github.com/metanorma/reverse_adoc/actions?workflow=windows"]
6
+ image:https://github.com/metanorma/reverse_adoc/workflows/ubuntu/badge.svg["Build Status", link="https://github.com/metanorma/reverse_adoc/actions?workflow=ubuntu"]
5
7
  image:https://codeclimate.com/github/metanorma/reverse_adoc/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/reverse_adoc"]
6
- image:https://ci.appveyor.com/api/projects/status/s4st0ft8moay90m6?svg=true["Appveyor Build Status", link="https://ci.appveyor.com/project/ribose/reverse-asciidoctor"]
8
+ image:https://img.shields.io/github/issues-pr-raw/metanorma/reverse_adoc.svg["Pull Requests", link="https://github.com/metanorma/reverse_adoc/pulls"]
9
+ image:https://img.shields.io/github/commits-since/metanorma/reverse_adoc/latest.svg["Commits since latest",link="https://github.com/metanorma/reverse_adoc/releases"]
7
10
 
8
11
  == Purpose
9
12
 
@@ -41,10 +44,21 @@ $ reverse_adoc file.html > file.adoc
41
44
  $ cat file.html | reverse_adoc > file.adoc
42
45
  ----
43
46
 
47
+ === XML smrl description to AsciiDoc: `reverse_adoc`
48
+
49
+ Convert XML smrl description files to AsciiDoc:
50
+
51
+ [source,console]
52
+ ----
53
+ $ reverse_adoc -f smrl_description descriptions.xml > file.adoc
54
+ $ cat descriptions.xml | reverse_adoc -f smrl_description > file.adoc
55
+ ----
56
+
44
57
  [source,console]
45
58
  ----
46
59
  $ reverse_adoc -h
47
60
  Usage: reverse_adoc [options] <file>
61
+ -f, --input_format Supply input format to choose converter(html or smrl_description)
48
62
  -m, --mathml2asciimath Convert MathML to AsciiMath
49
63
  -o, --output=FILENAME Output file to write to
50
64
  -e, --external-images Export images if data URI
@@ -92,6 +106,13 @@ document, and it may not cope with ordered lists or headings with customised app
92
106
  For best results, reset the styles in the document you're converting to those in
93
107
  the default `Normal.dot` template.
94
108
 
109
+ NOTE: `w2a` requires the command-line version of LibreOffice, `soffice`. As it turns out,
110
+ LibreOffice v6 appears to render formulae in HTML as images instead of MathML expressions;
111
+ use LibreOffice v5. If you have both LibreOffice v5 and LibreOffice v6 installed, make sure
112
+ that your OS path searches for the LibreOffice v5 version of `soffice` first; e.g. on Mac,
113
+ include something like `/Applications/LibreOffice5.4.7.2.app/Contents/MacOS` in your PATH
114
+ environment.
115
+
95
116
  NOTE: Some information in OOMML is not preserved in the export to MathML from LibreOffice;
96
117
  in particular, font shifts such as double-struck fonts.
97
118
  The LibreOffice exporter does seem to drop some text (possibly associated with
@@ -242,6 +263,18 @@ AsciiMath, and fail. But of course, MathJax has no problem with MathML, and some
242
263
  on the Asciidoctor output can ensure that the MathML is treated by MathJax (or whatever else
243
264
  uses the output) as such; so this is still much better than nothing for stem processing.
244
265
 
266
+ === Word cleanup
267
+
268
+ This gem is routinely used in the Metanorma project to export Word documents to Asciidoctor.
269
+ The HTML export from Word that the gem uses, from LibreOffice, is much cleaner than the
270
+ native HTML 4 export from Word; but it has some infelicities which this gem cleans up:
271
+
272
+ * The HTML export has trouble with subscripts, and routinely exports them as headings; the `w2a`
273
+ script tries to clean them up.
274
+ * The `w2a` cleans up spaces, but it does not strip them.
275
+ * Spaces are removed from anchors and cross-references.
276
+ * Double underscores are removed from anchors and cross-references.
277
+ * Cross-references to `_GoBack` and to `_Toc` followed by numbers (used to construct tables of contents) are ignored.
245
278
 
246
279
  == Ruby library usage
247
280
 
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # Usage: reverse_asciidoctor [FILE]...
3
3
  # Usage: cat FILE | reverse_asciidoctor
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+
4
7
  require 'reverse_asciidoctor'
5
8
  require 'optparse'
6
9
  require 'fileutils'
@@ -20,6 +23,10 @@ OptionParser.new do |opts|
20
23
  ReverseAsciidoctor.config.external_images = true
21
24
  end
22
25
 
26
+ opts.on('-f', '--input_format [html, smrl_description]', 'Unknown input format (default: html)') do |v|
27
+ ReverseAsciidoctor.config.input_format = v
28
+ end
29
+
23
30
  opts.on('-u', '--unknown_tags [pass_through, drop, bypass, raise]', 'Unknown tag handling (default: pass_through)') do |v|
24
31
  ReverseAsciidoctor.config.unknown_tags = v
25
32
  end
data/bin/w2a CHANGED
@@ -1,25 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+
4
7
  require 'word-to-markdown'
5
8
  require 'optparse'
6
9
  require 'reverse_asciidoctor'
7
10
 
8
- def scrub_whitespace(string)
9
- string = string.dup
10
- string.gsub!('&nbsp;', ' ') # HTML encoded spaces
11
- string.sub!(/\A[[:space:]]+/, '') # document leading whitespace
12
- string.sub!(/[[:space:]]+\z/, '') # document trailing whitespace
13
- string.gsub!(/([ ]+)$/, '') # line trailing whitespace
14
- string.gsub!(/\n\n\n\n/, "\n\n") # Quadruple line breaks
15
- string.delete!(' ') # Unicode non-breaking spaces, injected as tabs
16
- # following added by me
17
- string.gsub!(%r{<h[1-9][^>]*></h1>}, " ") # I don't know why Libre Office is inserting them, but they need to go
18
- string.gsub!(%r{<h1[^>]* style="vertical-align: super;[^>]*>([^<]+)</h1>},
19
- "<sup>\\1</sup>") # I absolutely don't know why Libre Office is rendering superscripts as h1
20
- string
21
- end
22
-
23
11
  ARGV.push('-h') if ARGV.empty?
24
12
 
25
13
  OptionParser.new do |opts|
@@ -63,11 +51,11 @@ if ReverseAsciidoctor.config.external_images && ReverseAsciidoctor.config.destin
63
51
  end
64
52
 
65
53
  ReverseAsciidoctor.config.sourcedir = Dir.mktmpdir
66
- # puts "ReverseAsciidoctor.config.sourcedir #{ReverseAsciidoctor.config.sourcedir}"
67
54
 
68
55
  doc = WordToMarkdown.new(filename, ReverseAsciidoctor.config.sourcedir)
56
+ #File.open("test.html", "w:UTF-8") { |f| f.write doc.document.html }
69
57
  adoc_content = ReverseAsciidoctor.convert(
70
- scrub_whitespace(doc.document.html),
58
+ ReverseAsciidoctor.cleaner.preprocess_word_html(doc.document.html),
71
59
  WordToMarkdown::REVERSE_MARKDOWN_OPTIONS
72
60
  )
73
61
  # puts scrub_whitespace(doc.document.html)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'digest'
2
4
  require 'nokogiri'
3
5
  require 'reverse_asciidoctor/version'
@@ -6,55 +8,14 @@ require 'reverse_asciidoctor/cleaner'
6
8
  require 'reverse_asciidoctor/config'
7
9
  require 'reverse_asciidoctor/converters'
8
10
  require 'reverse_asciidoctor/converters/base'
9
- require 'reverse_asciidoctor/converters/a'
10
- require 'reverse_asciidoctor/converters/aside'
11
- require 'reverse_asciidoctor/converters/audio'
12
- require 'reverse_asciidoctor/converters/blockquote'
13
- require 'reverse_asciidoctor/converters/br'
14
- require 'reverse_asciidoctor/converters/bypass'
15
- require 'reverse_asciidoctor/converters/code'
16
- require 'reverse_asciidoctor/converters/div'
17
- require 'reverse_asciidoctor/converters/drop'
18
- require 'reverse_asciidoctor/converters/em'
19
- require 'reverse_asciidoctor/converters/figure'
20
- require 'reverse_asciidoctor/converters/h'
21
- require 'reverse_asciidoctor/converters/head'
22
- require 'reverse_asciidoctor/converters/hr'
23
- require 'reverse_asciidoctor/converters/ignore'
24
- require 'reverse_asciidoctor/converters/img'
25
- require 'reverse_asciidoctor/converters/mark'
26
- require 'reverse_asciidoctor/converters/li'
27
- require 'reverse_asciidoctor/converters/ol'
28
- require 'reverse_asciidoctor/converters/p'
29
- require 'reverse_asciidoctor/converters/pass_through'
30
- require 'reverse_asciidoctor/converters/pre'
31
- require 'reverse_asciidoctor/converters/q'
32
- require 'reverse_asciidoctor/converters/strong'
33
- require 'reverse_asciidoctor/converters/sup'
34
- require 'reverse_asciidoctor/converters/sub'
35
- require 'reverse_asciidoctor/converters/table'
36
- require 'reverse_asciidoctor/converters/td'
37
- require 'reverse_asciidoctor/converters/th'
38
- require 'reverse_asciidoctor/converters/text'
39
- require 'reverse_asciidoctor/converters/tr'
40
- require 'reverse_asciidoctor/converters/video'
41
- require 'reverse_asciidoctor/converters/math'
42
11
 
43
12
  module ReverseAsciidoctor
44
-
45
13
  def self.convert(input, options = {})
46
- root = case input
47
- when String then Nokogiri::HTML(input).root
48
- when Nokogiri::XML::Document then input.root
49
- when Nokogiri::XML::Node then input
50
- end
51
-
52
- root or return ''
53
-
54
- config.with(options) do
55
- result = ReverseAsciidoctor::Converters.lookup(root.name).convert(root)
56
- cleaner.tidy(result)
57
- end
14
+ type = config.input_format
15
+ name = "#{type}_converter"
16
+ require "reverse_asciidoctor/#{type}_converter"
17
+ constant = name.split('_').map(&:capitalize).join.to_s
18
+ ReverseAsciidoctor.const_get(constant).convert(input, options)
58
19
  end
59
20
 
60
21
  def self.config
@@ -66,5 +27,4 @@ module ReverseAsciidoctor
66
27
  def self.cleaner
67
28
  @cleaner ||= Cleaner.new
68
29
  end
69
-
70
30
  end
@@ -64,6 +64,29 @@ module ReverseAsciidoctor
64
64
  string.gsub(/(\*\*|~~|__)\s([\.!\?'"])/, "\\1".strip + "\\2")
65
65
  end
66
66
 
67
+ # preprocesses HTML, rather than postprocessing it
68
+ def preprocess_word_html(string)
69
+ clean_headings(scrub_whitespace(string.dup))
70
+ end
71
+
72
+ def scrub_whitespace(string)
73
+ string.gsub!(/&nbsp;|\&#xA0;|\u00a0/i, '&#xA0;') # HTML encoded spaces
74
+ string.sub!(/^\A[[:space:]]+/m, '') # document leading whitespace
75
+ string.sub!(/[[:space:]]+\z$/m, '') # document trailing whitespace
76
+ string.gsub!(/([ ]+)$/, ' ') # line trailing whitespace
77
+ string.gsub!(/\n\n\n\n/, "\n\n") # Quadruple line breaks
78
+ #string.delete!('?| ') # Unicode non-breaking spaces, injected as tabs
79
+ string
80
+ end
81
+
82
+ # following added by me
83
+ def clean_headings(string)
84
+ string.gsub!(%r{<h([1-9])[^>]*></h\1>}, " ") # I don't know why Libre Office is inserting them, but they need to go
85
+ string.gsub!(%r{<h([1-9])[^>]* style="vertical-align: super;[^>]*>(.+?)</h\1>},
86
+ "<sup>\\2</sup>") # I absolutely don't know why Libre Office is rendering superscripts as h1
87
+ string
88
+ end
89
+
67
90
  private
68
91
 
69
92
  def preserve_border_whitespaces(string, options = {}, &block)