html2doc 1.0.7 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +6 -37
- data/.gitignore +2 -0
- data/.hound.yml +3 -1
- data/.rubocop.yml +7 -7
- data/Gemfile +2 -2
- data/Rakefile +1 -1
- data/bin/html2doc +1 -2
- data/bin/rspec +1 -1
- data/html2doc.gemspec +8 -9
- data/lib/html2doc.rb +0 -3
- data/lib/html2doc/base.rb +58 -47
- data/lib/html2doc/lists.rb +47 -42
- data/lib/html2doc/math.rb +100 -73
- data/lib/html2doc/mime.rb +53 -37
- data/lib/html2doc/notes.rb +42 -36
- data/lib/html2doc/version.rb +1 -1
- data/spec/html2doc_spec.rb +575 -517
- metadata +44 -46
- data/.rubocop.ribose.yml +0 -65
- data/.rubocop.tb.yml +0 -650
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bfc410fe0fcf441579436aaf3befc8929176ee8f531e68606b4ca2252934e222
         | 
| 4 | 
            +
              data.tar.gz: 8e7516c957ed9cb3de6bfffaab8b472333a5a727adce16c5fc5fda3e78c4767d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 623bd220a0631e9304ba49d586ea76824fd3a772b2afdfbf557903cafdecc942ba90a346a8947b818aa0d2e74043cedefb68a9ee859b4e1b4f76241236730086
         | 
| 7 | 
            +
              data.tar.gz: 9dc7ea304707dd234fb5a2c16a5377583cce3b17839c90d51f5a172ebe704751a45ebe4dc832362d34ca1d7e44b96ce39f6afa943098fee7660db67c2049d6a0
         | 
    
        data/.github/workflows/rake.yml
    CHANGED
    
    | @@ -4,7 +4,7 @@ name: rake | |
| 4 4 |  | 
| 5 5 | 
             
            on:
         | 
| 6 6 | 
             
              push:
         | 
| 7 | 
            -
                branches: [ master, main | 
| 7 | 
            +
                branches: [ master, main ]
         | 
| 8 8 | 
             
                tags: [ v* ]
         | 
| 9 9 | 
             
              pull_request:
         | 
| 10 10 |  | 
| @@ -16,48 +16,17 @@ jobs: | |
| 16 16 | 
             
                strategy:
         | 
| 17 17 | 
             
                  fail-fast: false
         | 
| 18 18 | 
             
                  matrix:
         | 
| 19 | 
            -
                    ruby: [ '2.6', '2.5', '2.4' ]
         | 
| 19 | 
            +
                    ruby: [ '3.0', '2.7', '2.6', '2.5', '2.4' ]
         | 
| 20 20 | 
             
                    os: [ ubuntu-latest, windows-latest, macos-latest ]
         | 
| 21 21 | 
             
                    experimental: [ false ]
         | 
| 22 | 
            -
                    include:
         | 
| 23 | 
            -
                      - ruby: '2.7'
         | 
| 24 | 
            -
                        os: 'ubuntu-latest'
         | 
| 25 | 
            -
                        experimental: true
         | 
| 26 | 
            -
                      - ruby: '2.7'
         | 
| 27 | 
            -
                        os: 'windows-latest'
         | 
| 28 | 
            -
                        experimental: true
         | 
| 29 | 
            -
                      - ruby: '2.7'
         | 
| 30 | 
            -
                        os: 'macos-latest'
         | 
| 31 | 
            -
                        experimental: true
         | 
| 32 22 | 
             
                steps:
         | 
| 33 | 
            -
                  - uses: actions/checkout@ | 
| 23 | 
            +
                  - uses: actions/checkout@v2
         | 
| 24 | 
            +
                    with:
         | 
| 25 | 
            +
                      submodules: true
         | 
| 34 26 |  | 
| 35 27 | 
             
                  - uses: ruby/setup-ruby@v1
         | 
| 36 28 | 
             
                    with:
         | 
| 37 29 | 
             
                      ruby-version: ${{ matrix.ruby }}
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                  - uses: actions/cache@v1
         | 
| 40 | 
            -
                    with:
         | 
| 41 | 
            -
                      path: vendor/bundle
         | 
| 42 | 
            -
                      key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
         | 
| 43 | 
            -
                      restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                  - run: bundle config set path 'vendor/bundle'
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  - run: bundle install --jobs 4 --retry 3
         | 
| 30 | 
            +
                      bundler-cache: true
         | 
| 48 31 |  | 
| 49 32 | 
             
                  - run: bundle exec rake
         | 
| 50 | 
            -
             | 
| 51 | 
            -
              notify:
         | 
| 52 | 
            -
                name: Trigger notify workflow
         | 
| 53 | 
            -
                needs: rake
         | 
| 54 | 
            -
                runs-on: ubuntu-latest
         | 
| 55 | 
            -
                steps:
         | 
| 56 | 
            -
                  - name: Trigger notify workflow
         | 
| 57 | 
            -
                    uses: Sibz/github-status-action@v1
         | 
| 58 | 
            -
                    with:
         | 
| 59 | 
            -
                      authToken: ${{ secrets.GITHUB_TOKEN }}
         | 
| 60 | 
            -
                      context: 'tests-passed-successfully'
         | 
| 61 | 
            -
                      description: 'Tests passed successfully'
         | 
| 62 | 
            -
                      state: 'success'
         | 
| 63 | 
            -
                      sha: ${{ github.event.pull_request.head.sha || github.sha }}
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.hound.yml
    CHANGED
    
    
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -1,10 +1,10 @@ | |
| 1 | 
            -
            #  | 
| 2 | 
            -
            # https://github.com/ | 
| 3 | 
            -
            # All project-specific additions and overrides should be specified in this file.
         | 
| 4 | 
            -
             | 
| 1 | 
            +
            # Auto-generated by Cimas: Do not edit it manually!
         | 
| 2 | 
            +
            # See https://github.com/metanorma/cimas
         | 
| 5 3 | 
             
            inherit_from:
         | 
| 6 4 | 
             
              - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # local repo-specific modifications
         | 
| 7 | 
            +
            # ...
         | 
| 8 | 
            +
             | 
| 7 9 | 
             
            AllCops:
         | 
| 8 | 
            -
              TargetRubyVersion: 2. | 
| 9 | 
            -
            Rails:
         | 
| 10 | 
            -
              Enabled: true
         | 
| 10 | 
            +
              TargetRubyVersion: 2.4
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -10,6 +10,6 @@ end | |
| 10 10 |  | 
| 11 11 | 
             
            gemspec
         | 
| 12 12 |  | 
| 13 | 
            -
            if File.exist?  | 
| 14 | 
            -
              eval File.read( | 
| 13 | 
            +
            if File.exist? "Gemfile.devel"
         | 
| 14 | 
            +
              eval File.read("Gemfile.devel"), nil, "Gemfile.devel" # rubocop:disable Security/Eval
         | 
| 15 15 | 
             
            end
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/bin/html2doc
    CHANGED
    
    
    
        data/bin/rspec
    CHANGED
    
    
    
        data/html2doc.gemspec
    CHANGED
    
    | @@ -1,5 +1,4 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            lib = File.expand_path("../lib", __FILE__)
         | 
| 1 | 
            +
            lib = File.expand_path("lib", __dir__)
         | 
| 3 2 | 
             
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 3 | 
             
            require "html2doc/version"
         | 
| 5 4 |  | 
| @@ -16,8 +15,8 @@ Gem::Specification.new do |spec| | |
| 16 15 | 
             
                This gem is in active development.
         | 
| 17 16 | 
             
              DESCRIPTION
         | 
| 18 17 |  | 
| 19 | 
            -
              spec.homepage | 
| 20 | 
            -
              spec.licenses | 
| 18 | 
            +
              spec.homepage = "https://github.com/metanorma/html2doc"
         | 
| 19 | 
            +
              spec.licenses = ["CC-BY-SA-3.0", "BSD-2-Clause"]
         | 
| 21 20 |  | 
| 22 21 | 
             
              spec.bindir        = "bin"
         | 
| 23 22 | 
             
              spec.require_paths = ["lib"]
         | 
| @@ -25,14 +24,14 @@ Gem::Specification.new do |spec| | |
| 25 24 | 
             
              spec.test_files    = `git ls-files -- {spec}/*`.split("\n")
         | 
| 26 25 | 
             
              spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
         | 
| 27 26 |  | 
| 27 | 
            +
              spec.add_dependency "asciimath", "~> 2.0.2"
         | 
| 28 28 | 
             
              spec.add_dependency "htmlentities", "~> 4.3.4"
         | 
| 29 29 | 
             
              spec.add_dependency "image_size"
         | 
| 30 30 | 
             
              spec.add_dependency "mime-types"
         | 
| 31 | 
            -
              spec.add_dependency "nokogiri", "~> 1. | 
| 31 | 
            +
              spec.add_dependency "nokogiri", "~> 1.11"
         | 
| 32 | 
            +
              spec.add_dependency "plane1converter", "~> 0.0.1"
         | 
| 32 33 | 
             
              spec.add_dependency "thread_safe"
         | 
| 33 34 | 
             
              spec.add_dependency "uuidtools"
         | 
| 34 | 
            -
              spec.add_dependency "asciimath", "~> 2.0.0"
         | 
| 35 | 
            -
              spec.add_dependency "plane1converter", "~> 0.0.1"
         | 
| 36 35 |  | 
| 37 36 | 
             
              spec.add_development_dependency "byebug", "~> 9.1"
         | 
| 38 37 | 
             
              spec.add_development_dependency "equivalent-xml", "~> 0.6"
         | 
| @@ -40,8 +39,8 @@ Gem::Specification.new do |spec| | |
| 40 39 | 
             
              spec.add_development_dependency "guard-rspec", "~> 4.7"
         | 
| 41 40 | 
             
              spec.add_development_dependency "rake", "~> 12.0"
         | 
| 42 41 | 
             
              spec.add_development_dependency "rspec", "~> 3.6"
         | 
| 43 | 
            -
              spec.add_development_dependency " | 
| 42 | 
            +
              spec.add_development_dependency "rspec-match_fuzzy", "~> 0.1.3"
         | 
| 43 | 
            +
              spec.add_development_dependency "rubocop", "~> 1.5.2"
         | 
| 44 44 | 
             
              spec.add_development_dependency "simplecov", "~> 0.15"
         | 
| 45 45 | 
             
              spec.add_development_dependency "timecop", "~> 0.9"
         | 
| 46 | 
            -
              spec.add_development_dependency "rspec-match_fuzzy", "~> 0.1.3"
         | 
| 47 46 | 
             
            end
         | 
    
        data/lib/html2doc.rb
    CHANGED
    
    
    
        data/lib/html2doc/base.rb
    CHANGED
    
    | @@ -2,8 +2,6 @@ require "uuidtools" | |
| 2 2 | 
             
            require "asciimath"
         | 
| 3 3 | 
             
            require "htmlentities"
         | 
| 4 4 | 
             
            require "nokogiri"
         | 
| 5 | 
            -
            #require "xml/xslt"
         | 
| 6 | 
            -
            require "pp"
         | 
| 7 5 | 
             
            require "fileutils"
         | 
| 8 6 |  | 
| 9 7 | 
             
            module Html2Doc
         | 
| @@ -19,16 +17,26 @@ module Html2Doc | |
| 19 17 |  | 
| 20 18 | 
             
              def self.process_header(headerfile, hash)
         | 
| 21 19 | 
             
                return if headerfile.nil?
         | 
| 20 | 
            +
             | 
| 22 21 | 
             
                doc = File.read(headerfile, encoding: "utf-8")
         | 
| 23 | 
            -
                doc = header_image_cleanup(doc, hash[:dir1], hash[:filename], | 
| 22 | 
            +
                doc = header_image_cleanup(doc, hash[:dir1], hash[:filename],
         | 
| 23 | 
            +
                                           File.dirname(hash[:filename]))
         | 
| 24 24 | 
             
                File.open("#{hash[:dir1]}/header.html", "w:UTF-8") { |f| f.write(doc) }
         | 
| 25 25 | 
             
              end
         | 
| 26 26 |  | 
| 27 | 
            +
              def self.clear_dir(dir)
         | 
| 28 | 
            +
                Dir.foreach(dir) do |f|
         | 
| 29 | 
            +
                  fn = File.join(dir, f)
         | 
| 30 | 
            +
                  File.delete(fn) if f != "." && f != ".."
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                dir
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 27 35 | 
             
              def self.create_dir(filename, dir)
         | 
| 28 | 
            -
                 | 
| 36 | 
            +
                dir and return clear_dir(dir)
         | 
| 29 37 | 
             
                dir = "#{filename}_files"
         | 
| 30 38 | 
             
                Dir.mkdir(dir) unless File.exists?(dir)
         | 
| 31 | 
            -
                dir
         | 
| 39 | 
            +
                clear_dir(dir)
         | 
| 32 40 | 
             
              end
         | 
| 33 41 |  | 
| 34 42 | 
             
              def self.process_html(result, hash)
         | 
| @@ -64,7 +72,7 @@ module Html2Doc | |
| 64 72 |  | 
| 65 73 | 
             
              def self.to_xhtml(xml)
         | 
| 66 74 | 
             
                xml.gsub!(/<\?xml[^>]*>/, "")
         | 
| 67 | 
            -
                unless /<!DOCTYPE /.match xml
         | 
| 75 | 
            +
                unless /<!DOCTYPE /.match? xml
         | 
| 68 76 | 
             
                  xml = '<!DOCTYPE html SYSTEM
         | 
| 69 77 | 
             
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + xml
         | 
| 70 78 | 
             
                end
         | 
| @@ -76,34 +84,35 @@ module Html2Doc | |
| 76 84 | 
             
              DOCTYPE
         | 
| 77 85 |  | 
| 78 86 | 
             
              def self.from_xhtml(xml)
         | 
| 79 | 
            -
                xml.to_xml.sub(%{ xmlns="http://www.w3.org/1999/xhtml"}, "") | 
| 80 | 
            -
                  sub(DOCTYPE, "") | 
| 81 | 
            -
                  gsub(%{ />}, "/>")
         | 
| 87 | 
            +
                xml.to_xml.sub(%{ xmlns="http://www.w3.org/1999/xhtml"}, "")
         | 
| 88 | 
            +
                  .sub(DOCTYPE, "")
         | 
| 89 | 
            +
                  .gsub(%{ />}, "/>")
         | 
| 82 90 | 
             
              end
         | 
| 83 91 |  | 
| 84 | 
            -
              def self.msword_fix( | 
| 92 | 
            +
              def self.msword_fix(doc)
         | 
| 85 93 | 
             
                # brain damage in MSWord parser
         | 
| 86 | 
            -
                 | 
| 87 | 
            -
             | 
| 88 | 
            -
                 | 
| 89 | 
            -
             | 
| 90 | 
            -
                 | 
| 91 | 
            -
                 | 
| 92 | 
            -
                 | 
| 93 | 
            -
             | 
| 94 | 
            -
                 | 
| 95 | 
            -
                 | 
| 96 | 
            -
                 | 
| 97 | 
            -
                 | 
| 98 | 
            -
                 | 
| 99 | 
            -
                 | 
| 100 | 
            -
                 | 
| 101 | 
            -
                 | 
| 102 | 
            -
                 | 
| 94 | 
            +
                doc.gsub!(%r{<span style="mso-special-character:footnote"/>},
         | 
| 95 | 
            +
                          '<span style="mso-special-character:footnote"></span>')
         | 
| 96 | 
            +
                doc.gsub!(%r{<div style="mso-element:footnote-list"></div>},
         | 
| 97 | 
            +
                          '<div style="mso-element:footnote-list"/>')
         | 
| 98 | 
            +
                doc.gsub!(%r{(<a style="mso-comment-reference:[^>/]+)/>}, "\\1></a>")
         | 
| 99 | 
            +
                doc.gsub!(%r{<link rel="File-List"}, "<link rel=File-List")
         | 
| 100 | 
            +
                doc.gsub!(%r{<meta http-equiv="Content-Type"},
         | 
| 101 | 
            +
                          "<meta http-equiv=Content-Type")
         | 
| 102 | 
            +
                doc.gsub!(%r{></m:jc>}, "/>")
         | 
| 103 | 
            +
                doc.gsub!(%r{></v:stroke>}, "/>")
         | 
| 104 | 
            +
                doc.gsub!(%r{></v:f>}, "/>")
         | 
| 105 | 
            +
                doc.gsub!(%r{></v:path>}, "/>")
         | 
| 106 | 
            +
                doc.gsub!(%r{></o:lock>}, "/>")
         | 
| 107 | 
            +
                doc.gsub!(%r{></v:imagedata>}, "/>")
         | 
| 108 | 
            +
                doc.gsub!(%r{></w:wrap>}, "/>")
         | 
| 109 | 
            +
                doc.gsub!(%r{<(/)?m:(span|em)\b}, "<\\1\\2")
         | 
| 110 | 
            +
                doc.gsub!(%r{&tab;|&tab;},
         | 
| 111 | 
            +
                          '<span style="mso-tab-count:1">  </span>')
         | 
| 112 | 
            +
                doc.split(%r{(<m:oMath>|</m:oMath>)}).each_slice(4).map do |a|
         | 
| 103 113 | 
             
                  a.size > 2 and a[2] = a[2].gsub(/>\s+</, "><")
         | 
| 104 114 | 
             
                  a
         | 
| 105 115 | 
             
                end.join
         | 
| 106 | 
            -
                r
         | 
| 107 116 | 
             
              end
         | 
| 108 117 |  | 
| 109 118 | 
             
              PRINT_VIEW = <<~XML.freeze
         | 
| @@ -119,29 +128,30 @@ module Html2Doc | |
| 119 128 | 
             
                <meta http-equiv=Content-Type content="text/html; charset=utf-8"/>
         | 
| 120 129 | 
             
              XML
         | 
| 121 130 |  | 
| 122 | 
            -
              def self.define_head1(docxml,  | 
| 131 | 
            +
              def self.define_head1(docxml, _dir)
         | 
| 123 132 | 
             
                docxml.xpath("//*[local-name() = 'head']").each do |h|
         | 
| 124 133 | 
             
                  h.children.first.add_previous_sibling <<~XML
         | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 134 | 
            +
                    #{PRINT_VIEW}
         | 
| 135 | 
            +
                      <link rel="File-List" href="cid:filelist.xml"/>
         | 
| 127 136 | 
             
                  XML
         | 
| 128 137 | 
             
                end
         | 
| 129 138 | 
             
              end
         | 
| 130 139 |  | 
| 131 | 
            -
              def self.filename_substitute( | 
| 132 | 
            -
                if header_filename.nil?
         | 
| 133 | 
            -
             | 
| 134 | 
            -
                 | 
| 135 | 
            -
                   | 
| 140 | 
            +
              def self.filename_substitute(head, header_filename)
         | 
| 141 | 
            +
                return if header_filename.nil?
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                head.xpath(".//*[local-name() = 'style']").each do |s|
         | 
| 144 | 
            +
                  s1 = s.to_xml.gsub(/url\("[^"]+"\)/) do |m|
         | 
| 145 | 
            +
                    /FILENAME/.match?(m) ? "url(cid:header.html)" : m
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                  s.replace(s1)
         | 
| 136 148 | 
             
                end
         | 
| 137 | 
            -
                stylesheet
         | 
| 138 149 | 
             
              end
         | 
| 139 150 |  | 
| 140 | 
            -
              def self.stylesheet( | 
| 141 | 
            -
                (fn.nil? || fn.empty?)  | 
| 151 | 
            +
              def self.stylesheet(_filename, _header_filename, fn)
         | 
| 152 | 
            +
                (fn.nil? || fn.empty?) and
         | 
| 142 153 | 
             
                  fn = File.join(File.dirname(__FILE__), "wordstyle.css")
         | 
| 143 154 | 
             
                stylesheet = File.read(fn, encoding: "UTF-8")
         | 
| 144 | 
            -
                stylesheet = filename_substitute(stylesheet, header_filename, filename)
         | 
| 145 155 | 
             
                xml = Nokogiri::XML("<style/>")
         | 
| 146 156 | 
             
                xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
         | 
| 147 157 | 
             
                xml.root.to_s
         | 
| @@ -152,6 +162,7 @@ module Html2Doc | |
| 152 162 | 
             
                head = docxml.at("//*[local-name() = 'head']")
         | 
| 153 163 | 
             
                css = stylesheet(hash[:filename], hash[:header_file], hash[:stylesheet])
         | 
| 154 164 | 
             
                add_stylesheet(head, title, css)
         | 
| 165 | 
            +
                filename_substitute(head, hash[:header_file])
         | 
| 155 166 | 
             
                define_head1(docxml, hash[:dir1])
         | 
| 156 167 | 
             
                rootnamespace(docxml.root)
         | 
| 157 168 | 
             
              end
         | 
| @@ -180,13 +191,13 @@ module Html2Doc | |
| 180 191 | 
             
              end
         | 
| 181 192 |  | 
| 182 193 | 
             
              def self.bookmarks(docxml)
         | 
| 183 | 
            -
                docxml.xpath("//*[@id][not(@name)][not(@style = 'mso-element:footnote')]") | 
| 184 | 
            -
                   | 
| 185 | 
            -
                  next if  | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
                   | 
| 189 | 
            -
             | 
| 194 | 
            +
                docxml.xpath("//*[@id][not(@name)][not(@style = 'mso-element:footnote')]")
         | 
| 195 | 
            +
                  .each do |x|
         | 
| 196 | 
            +
                  next if x["id"].empty? ||
         | 
| 197 | 
            +
                    %w(shapetype v:shapetype shape v:shape).include?(x.name)
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  if x.children.empty? then x.add_child("<a name='#{x['id']}'></a>")
         | 
| 200 | 
            +
                  else x.children.first.previous = "<a name='#{x['id']}'></a>"
         | 
| 190 201 | 
             
                  end
         | 
| 191 202 | 
             
                  x.delete("id")
         | 
| 192 203 | 
             
                end
         | 
    
        data/lib/html2doc/lists.rb
    CHANGED
    
    | @@ -2,83 +2,87 @@ require "uuidtools" | |
| 2 2 | 
             
            require "asciimath"
         | 
| 3 3 | 
             
            require "htmlentities"
         | 
| 4 4 | 
             
            require "nokogiri"
         | 
| 5 | 
            -
            require "uuidtools"
         | 
| 6 5 |  | 
| 7 6 | 
             
            module Html2Doc
         | 
| 8 | 
            -
              def self.style_list( | 
| 7 | 
            +
              def self.style_list(elem, level, liststyle, listnumber)
         | 
| 9 8 | 
             
                return unless liststyle
         | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 9 | 
            +
             | 
| 10 | 
            +
                if elem["style"]
         | 
| 11 | 
            +
                  elem["style"] += ";"
         | 
| 12 12 | 
             
                else
         | 
| 13 | 
            -
                   | 
| 13 | 
            +
                  elem["style"] = ""
         | 
| 14 14 | 
             
                end
         | 
| 15 | 
            -
                 | 
| 15 | 
            +
                elem["style"] += "mso-list:#{liststyle} level#{level} lfo#{listnumber};"
         | 
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| 18 | 
            -
              def self.list_add1( | 
| 19 | 
            -
                if [ | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 18 | 
            +
              def self.list_add1(elem, liststyles, listtype, level)
         | 
| 19 | 
            +
                if %i[ul ol].include? listtype
         | 
| 20 | 
            +
                  list_add(elem.xpath(".//ul") - elem.xpath(".//ul//ul | .//ol//ul"),
         | 
| 21 | 
            +
                           liststyles, :ul, level + 1)
         | 
| 22 | 
            +
                  list_add(elem.xpath(".//ol") - elem.xpath(".//ul//ol | .//ol//ol"),
         | 
| 23 | 
            +
                           liststyles, :ol, level + 1)
         | 
| 24 | 
            +
                else
         | 
| 25 | 
            +
                  list_add(elem.xpath(".//ul") - elem.xpath(".//ul//ul | .//ol//ul"),
         | 
| 26 | 
            +
                           liststyles, listtype, level + 1)
         | 
| 27 | 
            +
                  list_add(elem.xpath(".//ol") - elem.xpath(".//ul//ol | .//ol//ol"),
         | 
| 28 | 
            +
                           liststyles, listtype, level + 1)
         | 
| 29 | 
            +
                end
         | 
| 30 30 | 
             
              end
         | 
| 31 31 |  | 
| 32 32 | 
             
              def self.list_add(xpath, liststyles, listtype, level)
         | 
| 33 | 
            -
                xpath.each_with_index do | | 
| 33 | 
            +
                xpath.each_with_index do |l, _i|
         | 
| 34 34 | 
             
                  @listnumber += 1 if level == 1
         | 
| 35 | 
            -
                   | 
| 36 | 
            -
                   | 
| 37 | 
            -
                  ( | 
| 35 | 
            +
                  l["seen"] = true if level == 1
         | 
| 36 | 
            +
                  l["id"] ||= UUIDTools::UUID.random_create
         | 
| 37 | 
            +
                  (l.xpath(".//li") - l.xpath(".//ol//li | .//ul//li")).each do |li|
         | 
| 38 38 | 
             
                    style_list(li, level, liststyles[listtype], @listnumber)
         | 
| 39 39 | 
             
                    list_add1(li, liststyles, listtype, level)
         | 
| 40 40 | 
             
                  end
         | 
| 41 | 
            -
                   | 
| 42 | 
            -
             | 
| 43 | 
            -
                     | 
| 41 | 
            +
                  l.xpath(".//ul[not(ancestor::li/ancestor::*/@id = '#{l['id']}')] | "\
         | 
| 42 | 
            +
                          ".//ol[not(ancestor::li/ancestor::*/@id = '#{l['id']}')]")
         | 
| 43 | 
            +
                    .each do |li|
         | 
| 44 | 
            +
                    list_add1(li.parent, liststyles, listtype, level - 1)
         | 
| 44 45 | 
             
                  end
         | 
| 45 46 | 
             
                end
         | 
| 46 47 | 
             
              end
         | 
| 47 48 |  | 
| 48 | 
            -
              def self.list2para( | 
| 49 | 
            -
                return if  | 
| 50 | 
            -
             | 
| 51 | 
            -
                 | 
| 52 | 
            -
                 | 
| 53 | 
            -
                 | 
| 49 | 
            +
              def self.list2para(list)
         | 
| 50 | 
            +
                return if list.xpath("./li").empty?
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                list.xpath("./li").first["class"] ||= "MsoListParagraphCxSpFirst"
         | 
| 53 | 
            +
                list.xpath("./li").last["class"] ||= "MsoListParagraphCxSpLast"
         | 
| 54 | 
            +
                list.xpath("./li/p").each { |p| p["class"] ||= "MsoListParagraphCxSpMiddle" }
         | 
| 55 | 
            +
                list.xpath("./li").each do |l|
         | 
| 54 56 | 
             
                  l.name = "p"
         | 
| 55 57 | 
             
                  l["class"] ||= "MsoListParagraphCxSpMiddle"
         | 
| 56 58 | 
             
                  l&.first_element_child&.name == "p" and
         | 
| 57 59 | 
             
                    l.first_element_child.replace(l.first_element_child.children)
         | 
| 58 60 | 
             
                end
         | 
| 59 | 
            -
                 | 
| 61 | 
            +
                list.replace(list.children)
         | 
| 60 62 | 
             
              end
         | 
| 61 63 |  | 
| 62 64 | 
             
              TOPLIST = "[not(ancestor::ul) and not(ancestor::ol)]".freeze
         | 
| 63 65 |  | 
| 64 | 
            -
              def self.lists1(docxml, liststyles,  | 
| 65 | 
            -
                case  | 
| 66 | 
            +
              def self.lists1(docxml, liststyles, style)
         | 
| 67 | 
            +
                case style
         | 
| 66 68 | 
             
                when :ul then list_add(docxml.xpath("//ul[not(@class)]#{TOPLIST}"),
         | 
| 67 | 
            -
             | 
| 69 | 
            +
                                       liststyles, :ul, 1)
         | 
| 68 70 | 
             
                when :ol then list_add(docxml.xpath("//ol[not(@class)]#{TOPLIST}"),
         | 
| 69 71 | 
             
                                       liststyles, :ol, 1)
         | 
| 70 72 | 
             
                else
         | 
| 71 | 
            -
                  list_add(docxml.xpath("//ol[@class = '#{ | 
| 72 | 
            -
                                        "//ul[@class = '#{ | 
| 73 | 
            -
                  liststyles,  | 
| 73 | 
            +
                  list_add(docxml.xpath("//ol[@class = '#{style}']#{TOPLIST} | "\
         | 
| 74 | 
            +
                                        "//ul[@class = '#{style}']#{TOPLIST}"),
         | 
| 75 | 
            +
                  liststyles, style, 1)
         | 
| 74 76 | 
             
                end
         | 
| 75 77 | 
             
              end
         | 
| 76 78 |  | 
| 77 79 | 
             
              def self.lists_unstyled(docxml, liststyles)
         | 
| 78 | 
            -
                 | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 80 | 
            +
                liststyles.has_key?(:ul) and
         | 
| 81 | 
            +
                  list_add(docxml.xpath("//ul#{TOPLIST}[not(@seen)]"),
         | 
| 82 | 
            +
                           liststyles, :ul, 1)
         | 
| 83 | 
            +
                liststyles.has_key?(:ol) and
         | 
| 84 | 
            +
                  list_add(docxml.xpath("//ol#{TOPLIST}[not(@seen)]"),
         | 
| 85 | 
            +
                           liststyles, :ul, 1)
         | 
| 82 86 | 
             
                docxml.xpath("//ul[@seen] | //ol[@seen]").each do |l|
         | 
| 83 87 | 
             
                  l.delete("seen")
         | 
| 84 88 | 
             
                end
         | 
| @@ -86,6 +90,7 @@ module Html2Doc | |
| 86 90 |  | 
| 87 91 | 
             
              def self.lists(docxml, liststyles)
         | 
| 88 92 | 
             
                return if liststyles.nil?
         | 
| 93 | 
            +
             | 
| 89 94 | 
             
                @listnumber = 0
         | 
| 90 95 | 
             
                liststyles.each_key { |k| lists1(docxml, liststyles, k) }
         | 
| 91 96 | 
             
                lists_unstyled(docxml, liststyles)
         |