html2doc 0.9.4 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcc9db6cc57352a2e100bf1c1ff4127518d79fb67b958f52cd36580a4ab0b716
4
- data.tar.gz: 93979a73373bad8d3405ce8dd621455b54514d3e2e0017d9d91096b038405edb
3
+ metadata.gz: 89f05f87cd25266b64654929b7087a07c912fcf8b24beb33f2faceb5123da190
4
+ data.tar.gz: de12518aafb1ac65bf1f4addf76f16ff246c58aa99561e321dc3d8af7cd0a623
5
5
  SHA512:
6
- metadata.gz: d5d29322e87a5ec048dfacd91fe3bb3ecc27478348062cae38cff7dfa3c30fb8fdca06a20cd248e87d50d48a483fa1e24e60bb3d195ab900fb80a65289090df4
7
- data.tar.gz: 2803cb07d404a133fd7debee942c79e95154e7eb703527c96a00b8f10a03219d36f99b414c0ef964bd3beec01aed178524b2068b8b6ce45771e5246556a769ee
6
+ metadata.gz: 535aa46b12785253d9b5ebacf7f0c70f2f7045a5367dbf3ae2c023188a6005be39f6f003574d7855ca8ca2e757ddcde2f5128602e18156699248281fa6db4502
7
+ data.tar.gz: 5452e2880c9ba6f231d02039e5f2b2054e5535c903539f34804c65aeb77b63361994fd604f9d3d92ce808244fa5c46e9fc790f747041955606a1a474bdd02449
@@ -1,28 +1,34 @@
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
5
  on:
6
6
  push:
7
7
  branches: [ master ]
8
8
  pull_request:
9
- branches: [ '**' ]
9
+ paths-ignore:
10
+ - .github/workflows/ubuntu.yml
11
+ - .github/workflows/windows.yml
10
12
 
11
13
  jobs:
12
14
  test-macos:
13
15
  name: Test on Ruby ${{ matrix.ruby }} macOS
14
16
  runs-on: macos-latest
17
+ continue-on-error: ${{ matrix.experimental }}
15
18
  strategy:
16
19
  fail-fast: false
17
20
  matrix:
18
21
  ruby: [ '2.6', '2.5', '2.4' ]
22
+ experimental: [false]
23
+ include:
24
+ - ruby: '2.7'
25
+ experimental: true
19
26
  steps:
20
27
  - uses: actions/checkout@master
21
28
  - name: Use Ruby
22
29
  uses: actions/setup-ruby@v1
23
30
  with:
24
31
  ruby-version: ${{ matrix.ruby }}
25
- architecture: 'x64'
26
32
  - name: Update gems
27
33
  run: |
28
34
  sudo gem install bundler --force
@@ -1,32 +1,56 @@
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
5
  on:
6
6
  push:
7
7
  branches: [ master ]
8
+ tags:
9
+ - '*'
8
10
  pull_request:
9
- branches: [ '**' ]
11
+ paths-ignore:
12
+ - .github/workflows/macos.yml
13
+ - .github/workflows/windows.yml
10
14
 
11
15
  jobs:
12
16
  test-linux:
13
17
  name: Test on Ruby ${{ matrix.ruby }} Ubuntu
14
18
  runs-on: ubuntu-latest
19
+ continue-on-error: ${{ matrix.experimental }}
15
20
  strategy:
16
21
  fail-fast: false
17
22
  matrix:
18
23
  ruby: [ '2.6', '2.5', '2.4' ]
24
+ experimental: [false]
25
+ include:
26
+ - ruby: '2.7'
27
+ experimental: true
19
28
  steps:
20
29
  - uses: actions/checkout@master
21
30
  - name: Use Ruby
22
31
  uses: actions/setup-ruby@v1
23
32
  with:
24
33
  ruby-version: ${{ matrix.ruby }}
25
- architecture: 'x64'
26
34
  - name: Update gems
27
35
  run: |
28
- gem install bundler
36
+ gem install bundler
29
37
  bundle install --jobs 4 --retry 3
30
38
  - name: Run specs
31
39
  run: |
32
40
  bundle exec rake
41
+ - name: Trigger repositories
42
+ if: matrix.ruby == '2.6'
43
+ env:
44
+ GH_USERNAME: metanorma-ci
45
+ GH_ACCESS_TOKEN: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
46
+ run: |
47
+ curl -LO --retry 3 https://raw.githubusercontent.com/metanorma/metanorma-build-scripts/master/trigger-gh-actions.sh
48
+ [[ -f ".github/workflows/dependent_repos.env" ]] && source .github/workflows/dependent_repos.env
49
+ CLIENT_PAYLOAD=$(cat <<EOF
50
+ "{ "ref": "${GITHUB_REF}", "repo": "${GITHUB_REPOSITORY}" }"
51
+ EOF
52
+ )
53
+ for repo in $REPOS
54
+ do
55
+ sh trigger-gh-actions.sh $ORGANISATION $repo $GH_USERNAME $GH_ACCESS_TOKEN $GITHUB_REPOSITORY "$CLIENT_PAYLOAD"
56
+ done
@@ -1,34 +1,39 @@
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
5
  on:
6
6
  push:
7
7
  branches: [ master ]
8
8
  pull_request:
9
- branches: [ '**' ]
9
+ paths-ignore:
10
+ - .github/workflows/macos.yml
11
+ - .github/workflows/ubuntu.yml
10
12
 
11
13
  jobs:
12
14
  test-windows:
13
15
  name: Test on Ruby ${{ matrix.ruby }} Windows
14
16
  runs-on: windows-latest
17
+ continue-on-error: ${{ matrix.experimental }}
15
18
  strategy:
16
19
  fail-fast: false
17
20
  matrix:
18
21
  ruby: [ '2.6', '2.5', '2.4' ]
22
+ experimental: [false]
23
+ include:
24
+ - ruby: '2.7'
25
+ experimental: true
19
26
  steps:
20
27
  - uses: actions/checkout@master
21
28
  - name: Use Ruby
22
29
  uses: actions/setup-ruby@v1
23
30
  with:
24
31
  ruby-version: ${{ matrix.ruby }}
25
- architecture: 'x64'
26
32
  - name: Update gems
27
33
  shell: pwsh
28
34
  run: |
29
- gem install bundler
35
+ gem install bundler
30
36
  bundle config --local path vendor/bundle
31
- bundle update
32
37
  bundle install --jobs 4 --retry 3
33
38
  - name: Run specs
34
39
  run: |
@@ -3,8 +3,9 @@
3
3
  https://github.com/metanorma/html2doc/workflows/main/badge.svg
4
4
 
5
5
  image:https://img.shields.io/gem/v/html2doc.svg["Gem Version", link="https://rubygems.org/gems/html2doc"]
6
- image:https://travis-ci.com/metanorma/html2doc.svg["Build Status", link="https://travis-ci.com/metanorma/html2doc"]
7
- image:https://ci.appveyor.com/api/projects/status/aspj42o70q3dnkf1?svg=true["Appveyor Build Status", link="https://ci.appveyor.com/project/metanorma/html2doc"]
6
+ image:https://github.com/metanorma/html2doc/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/metanorma/html2doc/actions?query=workflow%3Aubuntu"]
7
+ image:https://github.com/metanorma/html2doc/workflows/macos/badge.svg["OSX Build Status", link="https://github.com/metanorma/html2doc/actions?query=workflow%3Amacos"]
8
+ image:https://github.com/metanorma/html2doc/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/metanorma/html2doc/actions?query=workflow%3Awindows"]
8
9
  image:https://codeclimate.com/github/metanorma/html2doc/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/html2doc"]
9
10
  image:https://img.shields.io/github/issues-pr-raw/metanorma/html2doc.svg["Pull Requests", link="https://github.com/metanorma/html2doc/pulls"]
10
11
  image:https://img.shields.io/github/commits-since/metanorma/html2doc/latest.svg["Commits since latest",link="https://github.com/metanorma/html2doc/releases"]
@@ -23,9 +24,12 @@ This work is driven by the Word document generation procedure documented in http
23
24
 
24
25
  The gem currently does the following:
25
26
 
26
- * Convert any AsciiMath and MathML to Word's native mathematical formatting language, OOXML. Word supports copy-pasting MathML into Word and converting it into OOXML; however the conversion is not infallible (we have found problems with `\sum`: Word claims parameters were missing, and inserting dotted squares to indicate as much), and you may need to post-edit the OOXML.
27
+ * Convert any AsciiMath and MathML to Word's native mathematical formatting language, OOXML. Word supports copy-pasting MathML into Word and converting it into OOXML; however the conversion is not infallible (we have in the past found problems with `\sum`: Word claims parameters were missing, and inserting dotted squares to indicate as much), and you may need to post-edit the OOXML.
27
28
  ** The gem does attempt to repair the MathML input, to bring it in line with Word's OOXML's expectations. If you find any issues with AsciiMath or MathML input, please raise an issue.
28
- * Identify any footnotes in the document (defined as hyperlinks with attributes `class = "Footnote"` or `epub:type = "footnote"`), and render them as Microsoft Word footnotes.
29
+ * Identify any footnotes in the document (defined as hyperlinks with attributes `class = "Footnote"` or `epub:type = "footnote"`), and render them as Microsoft Word footnotes.
30
+ ** The corresponding footnote content is any `div` or `aside` element with the same `@id` attribute as the footnote points to; e.g. `<a href="#ftn1" epub:type="footnote"><sup>3</sup></a></span>`, pointing to `<aside id="ftn3">`.
31
+ ** By default, the footnote hyperlink contents are overwritten with the autonumbering element: `<a href="#ftn1" epub:type="footnote"><sup>1</sup></a>` is replaced with `<a style='mso-footnote-id:ftn1' href='#_ftn1' name='_ftnref1' title='' id='_ftnref1'><span class='MsoFootnoteReference'><span style='mso-special-character:footnote'/></span>`
32
+ ** If the footnote hyperlink already contains (as a child) an element marked up as `<span class='MsoFootnoteReference'>`, only that span is replaced by the Microsoft autonumber element; any text surrounding it is preserved in both the footnote reference and the footnote target. For example, `<a href="#ftn1" epub:type="footnote"><span class='MsoFootnoteReference'>1</span>)</a>` will render as the footnote _1)_, both in the link and the target.
29
33
  * Resize any local images in the HTML file to fit within the maximum page size. (Word will otherwise crash on reading the document.)
30
34
  * Optionally apply list styles with predefined bullet and numbering from a Word CSS to the unordered and ordered lists in the document, restarting numbering for each ordered list.
31
35
  * Convert all lists to native Word HTML rendering (using paragraphs with `MsoListParagraphCxSpFirst, MsoListParagraphCxSpMiddle, MsoListParagraphCxSpLast` styles)
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "nokogiri", ">= 1.10.4"
32
32
  spec.add_dependency "thread_safe"
33
33
  spec.add_dependency "uuidtools"
34
- spec.add_dependency "asciimath", "~> 1.0.9"
34
+ spec.add_dependency "asciimath", "~> 2.0.0"
35
35
 
36
36
  spec.add_development_dependency "byebug", "~> 9.1"
37
37
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
@@ -2,7 +2,7 @@ require "uuidtools"
2
2
  require "asciimath"
3
3
  require "htmlentities"
4
4
  require "nokogiri"
5
- require "pp"
5
+ require "uuidtools"
6
6
 
7
7
  module Html2Doc
8
8
  def self.style_list(li, level, liststyle, listnumber)
@@ -15,13 +15,8 @@ module Html2Doc
15
15
  li["style"] += "mso-list:#{liststyle} level#{level} lfo#{listnumber};"
16
16
  end
17
17
 
18
- def self.list_add(xpath, liststyles, listtype, level)
19
- xpath.each_with_index do |list, i|
20
- @listnumber += 1 if level == 1
21
- list["seen"] = true if level == 1
22
- (list.xpath(".//li") - list.xpath(".//ol//li | .//ul//li")).each do |li|
23
- style_list(li, level, liststyles[listtype], @listnumber)
24
- if [:ul, :ol].include? listtype
18
+ def self.list_add1(li, liststyles, listtype, level)
19
+ if [:ul, :ol].include? listtype
25
20
  list_add(li.xpath(".//ul") - li.xpath(".//ul//ul | .//ol//ul"),
26
21
  liststyles, :ul, level + 1)
27
22
  list_add(li.xpath(".//ol") - li.xpath(".//ul//ol | .//ol//ol"),
@@ -32,6 +27,20 @@ module Html2Doc
32
27
  list_add(li.xpath(".//ol") - li.xpath(".//ul//ol | .//ol//ol"),
33
28
  liststyles, listtype, level + 1)
34
29
  end
30
+ end
31
+
32
+ def self.list_add(xpath, liststyles, listtype, level)
33
+ xpath.each_with_index do |list, i|
34
+ @listnumber += 1 if level == 1
35
+ list["seen"] = true if level == 1
36
+ list["id"] ||= UUIDTools::UUID.random_create
37
+ (list.xpath(".//li") - list.xpath(".//ol//li | .//ul//li")).each do |li|
38
+ style_list(li, level, liststyles[listtype], @listnumber)
39
+ list_add1(li, liststyles, listtype, level)
40
+ end
41
+ list.xpath(".//ul[not(ancestor::li/ancestor::*/@id = '#{list['id']}')] | "\
42
+ ".//ol[not(ancestor::li/ancestor::*/@id = '#{list['id']}')]").each do |li|
43
+ list_add1(li.parent, liststyles, listtype, level-1)
35
44
  end
36
45
  end
37
46
  end
@@ -9,7 +9,8 @@ module Html2Doc
9
9
  encoding: "utf-8"))
10
10
 
11
11
  def self.asciimath_to_mathml1(x)
12
- AsciiMath.parse(HTMLEntities.new.decode(x)).to_mathml.
12
+ AsciiMath::MathMLBuilder.new(:msword => true).append_expression(
13
+ AsciiMath.parse(HTMLEntities.new.decode(x)).ast).to_s.
13
14
  gsub(/<math>/, "<math xmlns='http://www.w3.org/1998/Math/MathML'>")
14
15
  end
15
16
 
@@ -31,6 +32,9 @@ module Html2Doc
31
32
  next unless x.next_element && x.next_element != "mrow"
32
33
  x.next_element.wrap("<mrow/>")
33
34
  end
35
+ m.xpath(".//xmlns:mtext", docnamespaces).each do |x|
36
+ x.children = x.children.to_xml.gsub(/^\s/, "&#xA0;").gsub(/\s$/, "&#xA0;")
37
+ end
34
38
  m.add_namespace(nil, "http://www.w3.org/1998/Math/MathML")
35
39
  m
36
40
  end
@@ -68,6 +68,7 @@ module Html2Doc
68
68
  realSize = ImageSize.path(path).size
69
69
  s = [i["width"].to_i, i["height"].to_i]
70
70
  s = realSize if s[0].zero? && s[1].zero?
71
+ return [nil, nil] if realSize[0].nil? || realSize[1].nil?
71
72
  s[1] = s[0] * realSize[1] / realSize[0] if s[1].zero? && !s[0].zero?
72
73
  s[0] = s[1] * realSize[0] / realSize[1] if s[0].zero? && !s[1].zero?
73
74
  s = [(s[0] * maxheight / s[1]).ceil, maxheight] if s[1] > maxheight
@@ -15,7 +15,7 @@ module Html2Doc
15
15
  body = docxml.at("//body")
16
16
  list = body.add_child("<div style='mso-element:footnote-list'/>")
17
17
  footnotes.each_with_index do |f, i|
18
- fn = list.first.add_child(footnote_container(i + 1))
18
+ fn = list.first.add_child(footnote_container(docxml, i + 1))
19
19
  f.parent = fn.first
20
20
  footnote_div_to_p(f)
21
21
  end
@@ -33,13 +33,16 @@ module Html2Doc
33
33
  end
34
34
  end
35
35
 
36
- def self.footnote_container(i)
36
+ FN = "<span class='MsoFootnoteReference'>"\
37
+ "<span style='mso-special-character:footnote'/></span>".freeze
38
+
39
+ def self.footnote_container(docxml, i)
40
+ ref = docxml&.at("//a[@href='#_ftn#{i}']")&.children&.to_xml(indent: 0).
41
+ gsub(/>\n</, "><") || FN
37
42
  <<~DIV
38
43
  <div style='mso-element:footnote' id='ftn#{i}'>
39
44
  <a style='mso-footnote-id:ftn#{i}' href='#_ftn#{i}'
40
- name='_ftnref#{i}' title='' id='_ftnref#{i}'><span
41
- class='MsoFootnoteReference'><span
42
- style='mso-special-character:footnote'></span></span></div>
45
+ name='_ftnref#{i}' title='' id='_ftnref#{i}'>#{ref.strip}</a></div>
43
46
  DIV
44
47
  end
45
48
 
@@ -49,8 +52,17 @@ module Html2Doc
49
52
  note = docxml.at("//*[@name = '#{href}' or @id = '#{href}']")
50
53
  return false if note.nil?
51
54
  set_footnote_link_attrs(a, i)
52
- a.children = "<span class='MsoFootnoteReference'>"\
53
- "<span style='mso-special-character:footnote'/></span>"
55
+ if a.at("./span[@class = 'MsoFootnoteReference']")
56
+ a.children.each do |c|
57
+ if c.name == "span" and c["class"] == "MsoFootnoteReference"
58
+ c.replace(FN)
59
+ else
60
+ c.wrap("<span class='MsoFootnoteReference'></span>")
61
+ end
62
+ end
63
+ else
64
+ a.children = FN
65
+ end
54
66
  fn << transform_footnote_text(note)
55
67
  end
56
68
 
@@ -1,3 +1,3 @@
1
1
  module Html2Doc
2
- VERSION = "0.9.4".freeze
2
+ VERSION = "1.0.4".freeze
3
3
  end
@@ -372,11 +372,11 @@ RSpec.describe Html2Doc do
372
372
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
373
373
  to match_fuzzy(<<~OUTPUT)
374
374
  #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
375
- #{word_body("
375
+ #{word_body(%{
376
376
  <div><m:oMath>
377
- #{ASCII_MATH}<m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>\"integer\"</m:t></m:r>
377
+ <m:nary><m:naryPr><m:chr m:val="&#x2211;"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><m:r><m:t>=</m:t></m:r><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>"integer"</m:t></m:r><m:r><m:t>)</m:t></m:r>
378
378
  </m:oMath>
379
- </div>", '<div style="mso-element:footnote-list"/>')}
379
+ </div>}, '<div style="mso-element:footnote-list"/>')}
380
380
  #{WORD_FTR1}
381
381
  OUTPUT
382
382
  end
@@ -388,23 +388,38 @@ RSpec.describe Html2Doc do
388
388
  #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
389
389
  #{word_body("
390
390
  <div><m:oMath>
391
- <m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>integer</m:t></m:r>
391
+ <m:r><m:t>text</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>&#xA0;integer&#xA0;</m:t></m:r><m:r><m:t>)</m:t></m:r>
392
392
  </m:oMath>
393
393
  </div>", '<div style="mso-element:footnote-list"/>')}
394
394
  #{WORD_FTR1}
395
395
  OUTPUT
396
396
  end
397
397
 
398
+ it "processes spaces in MathML mtext" do
399
+ Html2Doc.process(html_input("<div><math xmlns='http://www.w3.org/1998/Math/MathML'>
400
+ <mrow><mi>H</mi><mtext> original </mtext><mi>J</mi></mrow>
401
+ </math></div>"), filename: "test", asciimathdelims: ["{{", "}}"])
402
+ expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
403
+ to match_fuzzy(<<~OUTPUT)
404
+ #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
405
+ #{word_body('<div><m:oMath>
406
+ <m:r><m:t>H</m:t></m:r><m:r><m:rPr><m:nor></m:nor></m:rPr><m:t>&#xA0;original&#xA0;</m:t></m:r><m:r><m:t>J</m:t></m:r>
407
+ </m:oMath>
408
+ </div>', '<div style="mso-element:footnote-list"/>')}
409
+ #{WORD_FTR1}
410
+ OUTPUT
411
+ end
412
+
398
413
  it "left-aligns AsciiMath" do
399
414
  Html2Doc.process(html_input("<div style='text-align:left;'>{{sum_(i=1)^n i^3=((n(n+1))/2)^2}}</div>"), filename: "test", asciimathdelims: ["{{", "}}"])
400
415
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
401
416
  to match_fuzzy(<<~OUTPUT)
402
417
  #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
403
- #{word_body("
404
- <div style=\"text-align:left;\"><m:oMathPara><m:oMathParaPr><m:jc m:val=\"left\"/></m:oMathParaPr><m:oMath>
405
- #{ASCII_MATH}
418
+ #{word_body(%{
419
+ <div style="text-align:left;"><m:oMathPara><m:oMathParaPr><m:jc m:val="left"/></m:oMathParaPr><m:oMath>
420
+ <m:nary><m:naryPr><m:chr m:val="&#x2211;"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><m:r><m:t>=</m:t></m:r><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>
406
421
  </m:oMath>
407
- </m:oMathPara></div>", '<div style="mso-element:footnote-list"/>')}
422
+ </m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
408
423
  #{WORD_FTR1}
409
424
  OUTPUT
410
425
  end
@@ -414,11 +429,11 @@ RSpec.describe Html2Doc do
414
429
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
415
430
  to match_fuzzy(<<~OUTPUT)
416
431
  #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
417
- #{word_body("
418
- <div style=\"text-align:right;\"><m:oMathPara><m:oMathParaPr><m:jc m:val=\"right\"/></m:oMathParaPr><m:oMath>
419
- #{ASCII_MATH}
432
+ #{word_body(%{
433
+ <div style="text-align:right;"><m:oMathPara><m:oMathParaPr><m:jc m:val="right"/></m:oMathParaPr><m:oMath>
434
+ <m:nary><m:naryPr><m:chr m:val="&#x2211;"></m:chr><m:limLoc m:val="undOvr"></m:limLoc><m:grow m:val="on"></m:grow><m:subHide m:val="off"></m:subHide><m:supHide m:val="off"></m:supHide></m:naryPr><m:sub><m:r><m:t>i=1</m:t></m:r></m:sub><m:sup><m:r><m:t>n</m:t></m:r></m:sup><m:e><m:sSup><m:e><m:r><m:t>i</m:t></m:r></m:e><m:sup><m:r><m:t>3</m:t></m:r></m:sup></m:sSup></m:e></m:nary><m:r><m:t>=</m:t></m:r><m:sSup><m:e><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:f><m:fPr><m:type m:val="bar"></m:type></m:fPr><m:num><m:r><m:t>n</m:t></m:r><m:d><m:dPr><m:sepChr m:val=","></m:sepChr></m:dPr><m:e><m:r><m:t>n+1</m:t></m:r></m:e></m:d></m:num><m:den><m:r><m:t>2</m:t></m:r></m:den></m:f></m:e></m:d></m:e><m:sup><m:r><m:t>2</m:t></m:r></m:sup></m:sSup>
420
435
  </m:oMath>
421
- </m:oMathPara></div>", '<div style="mso-element:footnote-list"/>')}
436
+ </m:oMathPara></div>}, '<div style="mso-element:footnote-list"/>')}
422
437
  #{WORD_FTR1}
423
438
  OUTPUT
424
439
  end
@@ -613,6 +628,26 @@ RSpec.describe Html2Doc do
613
628
  OUTPUT
614
629
  end
615
630
 
631
+ it "processes footnotes with text wrapping the footnote reference" do
632
+ simple_body = '<div>This is a very simple
633
+ document<a class="footnote" href="#a1">(<span class="MsoFootnoteReference">1</span>)</a> allegedly<a class="footnote" href="#a2">2</a></div>
634
+ <aside id="a1">Footnote</aside>
635
+ <aside id="a2">Other Footnote</aside>'
636
+ Html2Doc.process(html_input(simple_body), filename: "test")
637
+ expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
638
+ to match_fuzzy(<<~OUTPUT)
639
+ #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
640
+ #{word_body('<div>This is a very simple
641
+ document<a class="footnote" href="#_ftn1" style="mso-footnote-id:ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference">(</span><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span><span class="MsoFootnoteReference">)</span></a> allegedly<a class="footnote" href="#_ftn2" style="mso-footnote-id:ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a></div>',
642
+ '<div style="mso-element:footnote-list"><div style="mso-element:footnote" id="ftn1">
643
+ <p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn1" href="#_ftn1" name="_ftnref1" title="" id="_ftnref1"><span class="MsoFootnoteReference">(</span><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span><span class="MsoFootnoteReference">)</span></a>Footnote</p></div>
644
+ <div style="mso-element:footnote" id="ftn2">
645
+ <p id="" class="MsoFootnoteText"><a style="mso-footnote-id:ftn2" href="#_ftn2" name="_ftnref2" title="" id="_ftnref2"><span class="MsoFootnoteReference"><span style="mso-special-character:footnote"></span></span></a>Other Footnote</p></div>
646
+ </div>')}
647
+ #{WORD_FTR1}
648
+ OUTPUT
649
+ end
650
+
616
651
  it "extracts paragraphs from footnotes" do
617
652
  simple_body = '<div>This is a very simple
618
653
  document<a class="footnote" href="#a1">1</a> allegedly<a class="footnote" href="#a2">2</a></div>
@@ -635,15 +670,16 @@ RSpec.describe Html2Doc do
635
670
 
636
671
  it "labels lists with list styles" do
637
672
  simple_body = <<~BODY
638
- <div><ul>
639
- <li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
673
+ <div><ul id="0">
674
+ <li><div><p><ol id="1"><li><ul id="2"><li><p><ol id="3"><li><ol id="4"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li><div><ul id="5"><li>C</li></ul></div>
640
675
  BODY
641
676
  Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
642
677
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
643
678
  to match_fuzzy(<<~OUTPUT)
644
679
  #{WORD_HDR} #{DEFAULT_STYLESHEET} #{WORD_HDR_END}
645
680
  #{word_body('<div>
646
- <p style="mso-list:l1 level1 lfo1;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p></div>',
681
+ <p style="mso-list:l1 level1 lfo1;" class="MsoListParagraphCxSpFirst"><div><p class="MsoNormal"><p style="mso-list:l2 level2 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level4 lfo1;" class="MsoListParagraphCxSpFirst"><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpFirst">A</p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpMiddle">B<p class="MsoListParagraphCxSpMiddle">B2</p></p><p style="mso-list:l2 level5 lfo1;" class="MsoListParagraphCxSpLast">C</p></p></p></p></div></p><div><p style="mso-list:l1 level1 lfo2;" class="MsoListParagraphCxSpFirst">C</p></div>
682
+ </div>',
647
683
  '<div style="mso-element:footnote-list"/>')}
648
684
  #{WORD_FTR1}
649
685
  OUTPUT
@@ -653,8 +689,8 @@ RSpec.describe Html2Doc do
653
689
  it "restarts numbering of lists with list styles" do
654
690
  simple_body = <<~BODY
655
691
  <div>
656
- <ol><li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol>
657
- <ol><li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol></div>
692
+ <ol id="1"><li><div><p><ol id="2"><li><ul id="3"><li><p><ol id="4"><li><ol id="5"><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol>
693
+ <ol id="6"><li><div><p><ol id="7"><li><ul id="8"><li><p><ol id="9"><li><ol id="10"><li>A</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ol></div>
658
694
  BODY
659
695
  Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2"})
660
696
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
@@ -670,12 +706,12 @@ RSpec.describe Html2Doc do
670
706
 
671
707
  it "labels lists with multiple list styles" do
672
708
  simple_body = <<~BODY
673
- <div><ul class="steps">
674
- <li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
675
- <div><ul>
676
- <li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
677
- <div><ul class="other">
678
- <li><div><p><ol><li><ul><li><p><ol><li><ol><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
709
+ <div><ul class="steps" id="0">
710
+ <li><div><p><ol id="1"><li><ul id="2"><li><p><ol id="3"><li><ol id="4"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
711
+ <div><ul id="5">
712
+ <li><div><p><ol id="6"><li><ul id="7"><li><p><ol id="8"><li><ol id="9"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
713
+ <div><ul class="other" id="10">
714
+ <li><div><p><ol id="11"><li><ul id="12"><li><p><ol id="13"><li><ol id="14"><li>A</li><li><p>B</p><p>B2</p></li><li>C</li></ol></li></ol></p></li></ul></li></ol></p></div></li></ul></div>
679
715
  BODY
680
716
  Html2Doc.process(html_input(simple_body), filename: "test", liststyles: {ul: "l1", ol: "l2", steps: "l3"})
681
717
  expect(guid_clean(File.read("test.doc", encoding: "utf-8"))).
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html2doc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-30 00:00:00.000000000 Z
11
+ date: 2020-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: htmlentities
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.0.9
103
+ version: 2.0.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.0.9
110
+ version: 2.0.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: byebug
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -309,7 +309,7 @@ licenses:
309
309
  - CC-BY-SA-3.0
310
310
  - BSD-2-Clause
311
311
  metadata: {}
312
- post_install_message:
312
+ post_install_message:
313
313
  rdoc_options: []
314
314
  require_paths:
315
315
  - lib
@@ -324,9 +324,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
324
324
  - !ruby/object:Gem::Version
325
325
  version: '0'
326
326
  requirements: []
327
- rubyforge_project:
328
- rubygems_version: 2.7.6
329
- signing_key:
327
+ rubygems_version: 3.0.3
328
+ signing_key:
330
329
  specification_version: 4
331
330
  summary: Convert HTML document to Microsoft Word document
332
331
  test_files: []