isodoc 0.7.1 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -6
  3. data/README.adoc +3 -3
  4. data/lib/{isodoc → isodoc-yaml}/i18n-en.yaml +0 -0
  5. data/lib/{isodoc → isodoc-yaml}/i18n-fr.yaml +0 -0
  6. data/lib/{isodoc → isodoc-yaml}/i18n-zh-Hans.yaml +0 -0
  7. data/lib/isodoc.rb +13 -6
  8. data/lib/isodoc/class_utils.rb +24 -0
  9. data/lib/isodoc/common.rb +34 -0
  10. data/lib/isodoc/convert.rb +3 -16
  11. data/lib/isodoc/function.rb +4 -0
  12. data/lib/isodoc/{blocks.rb → function/blocks.rb} +2 -2
  13. data/lib/isodoc/{cleanup.rb → function/cleanup.rb} +4 -9
  14. data/lib/isodoc/{i18n.rb → function/i18n.rb} +13 -10
  15. data/lib/isodoc/{inline.rb → function/inline.rb} +2 -4
  16. data/lib/isodoc/{lists.rb → function/lists.rb} +5 -4
  17. data/lib/isodoc/{references.rb → function/references.rb} +4 -3
  18. data/lib/isodoc/{section.rb → function/section.rb} +4 -3
  19. data/lib/isodoc/{table.rb → function/table.rb} +3 -2
  20. data/lib/isodoc/{terms.rb → function/terms.rb} +3 -2
  21. data/lib/isodoc/{iso2wordhtml.rb → function/to_word_html.rb} +2 -3
  22. data/lib/isodoc/{utils.rb → function/utils.rb} +6 -22
  23. data/lib/isodoc/{xref_gen.rb → function/xref_gen.rb} +4 -3
  24. data/lib/isodoc/{xref_sect_gen.rb → function/xref_sect_gen.rb} +4 -3
  25. data/lib/isodoc/html_convert.rb +12 -0
  26. data/lib/isodoc/html_function.rb +4 -0
  27. data/lib/isodoc/{htmlconvert → html_function}/comments.rb +2 -3
  28. data/lib/isodoc/{htmlconvert → html_function}/footnotes.rb +3 -4
  29. data/lib/isodoc/{htmlconvert → html_function}/html.rb +5 -5
  30. data/lib/isodoc/iso/html/html_iso_titlepage.html +2 -2
  31. data/lib/isodoc/iso/{convert.rb → html_convert.rb} +1 -1
  32. data/lib/isodoc/iso/{wordconvert.rb → word_convert.rb} +0 -0
  33. data/lib/isodoc/metadata.rb +27 -12
  34. data/lib/isodoc/version.rb +1 -1
  35. data/lib/isodoc/{wordconvert/convert.rb → word_convert.rb} +9 -11
  36. data/lib/isodoc/word_function.rb +4 -0
  37. data/lib/isodoc/word_function/body.rb +149 -0
  38. data/lib/isodoc/{wordconvert → word_function}/comments.rb +2 -2
  39. data/lib/isodoc/word_function/footnotes.rb +81 -0
  40. data/lib/isodoc/word_function/postprocess.rb +116 -0
  41. data/spec/isodoc/blocks_spec.rb +17 -17
  42. data/spec/isodoc/cleanup_spec.rb +8 -8
  43. data/spec/isodoc/footnotes_spec.rb +2 -2
  44. data/spec/isodoc/i18n_spec.rb +4 -4
  45. data/spec/isodoc/inline_spec.rb +7 -7
  46. data/spec/isodoc/iso_spec.rb +5 -5
  47. data/spec/isodoc/lists_spec.rb +4 -4
  48. data/spec/isodoc/metadata_spec.rb +2 -2
  49. data/spec/isodoc/postproc_spec.rb +9 -9
  50. data/spec/isodoc/ref_spec.rb +3 -3
  51. data/spec/isodoc/section_spec.rb +6 -6
  52. data/spec/isodoc/table_spec.rb +1 -1
  53. data/spec/isodoc/terms_spec.rb +1 -1
  54. data/spec/isodoc/xref_spec.rb +11 -11
  55. metadata +35 -30
  56. data/lib/isodoc/htmlconvert/convert.rb +0 -13
  57. data/lib/isodoc/wordconvert/footnotes.rb +0 -81
  58. data/lib/isodoc/wordconvert/postprocess.rb +0 -115
  59. data/lib/isodoc/wordconvert/wordconvertmodule.rb +0 -150
@@ -1,7 +1,8 @@
1
1
  require "roman-numerals"
2
2
 
3
- module IsoDoc
4
- class Common
3
+ module IsoDoc::Function
4
+ module XrefGen
5
+
5
6
  @anchors = {}
6
7
 
7
8
  def get_anchors
@@ -103,7 +104,7 @@ module IsoDoc
103
104
  label = listlabel(depth, i + 1)
104
105
  label = "#{prev_label}.#{label}" unless prev_label.empty?
105
106
  label = "#{list_anchor[:xref]} #{label}" if refer_list
106
- li["id"] && @anchors[li["id"]] = { xref: "#{label})",
107
+ li["id"] && @anchors[li["id"]] = { xref: "#{label})",
107
108
  container: list_anchor[:container] }
108
109
  li.xpath(ns("./ol")).each do |ol|
109
110
  list_item_anchor_names(ol, list_anchor, depth + 1, label, false)
@@ -1,5 +1,6 @@
1
- module IsoDoc
2
- class Common
1
+ module IsoDoc::Function
2
+ module XrefSectGen
3
+
3
4
  def back_anchor_names(docxml)
4
5
  docxml.xpath(ns("//annex")).each_with_index do |c, i|
5
6
  annex_names(c, (65 + i).chr.to_s)
@@ -77,7 +78,7 @@ module IsoDoc
77
78
  end
78
79
 
79
80
  def annex_names(clause, num)
80
- @anchors[clause["id"]] = { label: annex_name_lbl(clause, num),
81
+ @anchors[clause["id"]] = { label: annex_name_lbl(clause, num),
81
82
  xref: "#{@annex_lbl} #{num}", level: 1 }
82
83
  clause.xpath(ns("./clause")).each_with_index do |c, i|
83
84
  annex_names1(c, "#{num}.#{i + 1}", 2)
@@ -0,0 +1,12 @@
1
+ require_relative "html_function/comments.rb"
2
+ require_relative "html_function/footnotes.rb"
3
+ require_relative "html_function/html.rb"
4
+
5
+ module IsoDoc
6
+ class HtmlConvert < ::IsoDoc::Convert
7
+
8
+ include HtmlFunction::Comments
9
+ include HtmlFunction::Footnotes
10
+ include HtmlFunction::Html
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module IsoDoc
2
+ module HtmlFunction
3
+ end
4
+ end
@@ -1,7 +1,6 @@
1
- require "uuidtools"
1
+ module IsoDoc::HtmlFunction
2
+ module Comments
2
3
 
3
- module IsoDoc
4
- class Convert < Common
5
4
  def in_comment
6
5
  @in_comment
7
6
  end
@@ -1,7 +1,6 @@
1
- require "uuidtools"
1
+ module IsoDoc::HtmlFunction
2
+ module Footnotes
2
3
 
3
- module IsoDoc
4
- class Convert < Common
5
4
  def footnotes(div)
6
5
  return if @footnotes.empty?
7
6
  @footnotes.each { |fn| div.parent << fn }
@@ -69,7 +68,7 @@ module IsoDoc
69
68
  end
70
69
  make_footnote(node, fn)
71
70
  end
72
-
71
+
73
72
  def make_footnote(node, fn)
74
73
  return if @seen_footnote.include?(fn)
75
74
  @in_footnote = true
@@ -1,6 +1,6 @@
1
- module IsoDoc
2
- class Convert < Common
3
- def make_body1(body, _docxml)
1
+ module IsoDoc::HtmlFunction
2
+ module Html
3
+ def make_body1(body, _docxml)
4
4
  body.div **{ class: "title-section" } do |div1|
5
5
  div1.p { |p| p << "&nbsp;" } # placeholder
6
6
  end
@@ -78,7 +78,7 @@ module IsoDoc
78
78
  docxml
79
79
  end
80
80
 
81
- def html_head()
81
+ def html_head()
82
82
  <<~HEAD.freeze
83
83
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
84
84
 
@@ -94,7 +94,7 @@ module IsoDoc
94
94
  HEAD
95
95
  end
96
96
 
97
- def html_button()
97
+ def html_button()
98
98
  '<button onclick="topFunction()" id="myBtn" '\
99
99
  'title="Go to top">Top</button>'.freeze
100
100
  end
@@ -6,9 +6,9 @@
6
6
  <p class="coverpage_techcommittee"><a
7
7
  name="CVP_Secretariat_Loca">Secretariat</a>: {{ secretariat }}</p>
8
8
 
9
- <div class="doctitle-en"><span class="subtitle">{{ doctitle }}</span></div>
9
+ <div class="doctitle-en"><span class="title">{{ doctitleintro }}</span> <span class="subtitle">{{ doctitlemain }}</span> <span class="part">{{ doctitlepart }}</span></div>
10
10
 
11
- <div class="doctitle-fr"><span class="subtitle">{{ docsubtitle }}</span></div>
11
+ <div class="doctitle-fr"><span class="title">{{ docsubtitleintro }}</span> <span class="subtitle">{{ docsubtitlemain }}</span> <span class="part">{{ docsubtitlepart }}</span></div>
12
12
 
13
13
  <div class="coverpage_docstage"><p>{{ stageabbr }} stage</p></div>
14
14
 
@@ -1,6 +1,6 @@
1
1
  module IsoDoc
2
2
  module Iso
3
- class Convert < IsoDoc::Convert
3
+ class HtmlConvert < IsoDoc::HtmlConvert
4
4
 
5
5
  def default_fonts(options)
6
6
  b = options[:bodyfont] ||
@@ -1,5 +1,3 @@
1
- require "htmlentities"
2
-
3
1
  module IsoDoc
4
2
  class Metadata
5
3
  DATETYPES = %w{published accessed created implemented obsoleted confirmed
@@ -10,11 +8,15 @@ module IsoDoc
10
8
  end
11
9
 
12
10
  def initialize(lang, script, labels)
13
- @metadata = { tc: "XXXX", sc: "XXXX", wg: "XXXX",
14
- editorialgroup: [],
15
- secretariat: "XXXX",
16
- obsoletes: nil,
17
- obsoletes_part: nil }
11
+ @metadata = {
12
+ tc: "XXXX",
13
+ sc: "XXXX",
14
+ wg: "XXXX",
15
+ editorialgroup: [],
16
+ secretariat: "XXXX",
17
+ obsoletes: nil,
18
+ obsoletes_part: nil
19
+ }
18
20
  DATETYPES.each { |w| @metadata["#{w}date".to_sym] = "XXX" }
19
21
  @lang = lang
20
22
  @script = script
@@ -90,7 +92,7 @@ module IsoDoc
90
92
  def iso?(org)
91
93
  name = org&.at(ns("./name"))&.text
92
94
  abbrev = org&.at(ns("./abbreviation"))&.text
93
- (abbrev == "ISO" ||
95
+ (abbrev == "ISO" ||
94
96
  name == "International Organization for Standardization" )
95
97
  end
96
98
 
@@ -163,7 +165,7 @@ module IsoDoc
163
165
  draftinfo += ", #{revdate}" if revdate
164
166
  draftinfo += ")"
165
167
  end
166
- Common::l10n(draftinfo, @lang, @script)
168
+ IsoDoc::Function::I18n::l10n(draftinfo, @lang, @script)
167
169
  end
168
170
 
169
171
  def version(isoxml, _out)
@@ -183,14 +185,20 @@ module IsoDoc
183
185
  end
184
186
  end
185
187
 
188
+ def part_title(part, partnum, subpartnum, lang)
189
+ return "" unless part
190
+ suffix = @c.encode(part.text, :hexadecimal)
191
+ partnum = "#{partnum}&ndash;#{subpartnum}" if partnum && subpartnum
192
+ suffix = "#{part_label(lang)}&nbsp;#{partnum}: " + suffix if partnum
193
+ suffix
194
+ end
195
+
186
196
  def compose_title(main, intro, part, partnum, subpartnum, lang)
187
197
  main = main.nil? ? "" : @c.encode(main.text, :hexadecimal)
188
198
  intro &&
189
199
  main = "#{@c.encode(intro.text, :hexadecimal)}&nbsp;&mdash; #{main}"
190
200
  if part
191
- suffix = @c.encode(part.text, :hexadecimal)
192
- partnum = "#{partnum}&ndash;#{subpartnum}" if partnum && subpartnum
193
- suffix = "#{part_label(lang)}&nbsp;#{partnum}: " + suffix if partnum
201
+ suffix = part_title(part, partnum, subpartnum, lang)
194
202
  main = "#{main}&nbsp;&mdash; #{suffix}"
195
203
  end
196
204
  main
@@ -202,8 +210,12 @@ module IsoDoc
202
210
  part = isoxml.at(ns("//title-part[@language='en']"))
203
211
  partnumber = isoxml.at(ns("//project-number/@part"))
204
212
  subpartnumber = isoxml.at(ns("//project-number/@subpart"))
213
+
214
+ set(:doctitlemain, @c.encode(main ? main.text : "", :hexadecimal))
205
215
  main = compose_title(main, intro, part, partnumber, subpartnumber, "en")
206
216
  set(:doctitle, main)
217
+ set(:doctitleintro, @c.encode(intro ? intro.text : "", :hexadecimal)) if intro
218
+ set(:doctitlepart, part_title(part, partnumber, subpartnumber, "en"))
207
219
  end
208
220
 
209
221
  def subtitle(isoxml, _out)
@@ -212,8 +224,11 @@ module IsoDoc
212
224
  part = isoxml.at(ns("//title-part[@language='fr']"))
213
225
  partnumber = isoxml.at(ns("//project-number/@part"))
214
226
  subpartnumber = isoxml.at(ns("//project-number/@subpart"))
227
+ set(:docsubtitlemain, @c.encode(main ? main.text : "", :hexadecimal))
215
228
  main = compose_title(main, intro, part, partnumber, subpartnumber, "fr")
216
229
  set(:docsubtitle, main)
230
+ set(:docsubtitleintro, @c.encode(intro ? intro.text : "", :hexadecimal)) if intro
231
+ set(:docsubtitlepart, part_title(part, partnumber, subpartnumber, "fr"))
217
232
  end
218
233
 
219
234
  def relations(isoxml, _out)
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "0.7.1".freeze
2
+ VERSION = "0.8".freeze
3
3
  end
@@ -1,11 +1,7 @@
1
- require "uuidtools"
2
- require "html2doc"
3
- require "liquid"
4
-
5
- require_relative "wordconvertmodule"
6
- require_relative "comments"
7
- require_relative "footnotes"
8
- require_relative "postprocess"
1
+ require_relative "word_function/comments.rb"
2
+ require_relative "word_function/footnotes.rb"
3
+ require_relative "word_function/body.rb"
4
+ require_relative "word_function/postprocess.rb"
9
5
 
10
6
  module IsoDoc
11
7
 
@@ -28,8 +24,10 @@ module IsoDoc
28
24
  end
29
25
  =end
30
26
 
31
- class WordConvert < Common
32
- #include WordConvertModule
27
+ class WordConvert < ::IsoDoc::Convert
28
+ include WordFunction::Comments
29
+ include WordFunction::Footnotes
30
+ include WordFunction::Body
31
+ include WordFunction::Postprocess
33
32
  end
34
33
  end
35
-
@@ -0,0 +1,4 @@
1
+ module IsoDoc
2
+ module WordFunction
3
+ end
4
+ end
@@ -0,0 +1,149 @@
1
+ module IsoDoc::WordFunction
2
+ module Body
3
+ def make_body1(body, _docxml)
4
+ body.div **{ class: "WordSection1" } do |div1|
5
+ div1.p { |p| p << "&nbsp;" } # placeholder
6
+ end
7
+ section_break(body)
8
+ end
9
+
10
+ def make_body2(body, docxml)
11
+ body.div **{ class: "WordSection2" } do |div2|
12
+ info docxml, div2
13
+ foreword docxml, div2
14
+ introduction docxml, div2
15
+ div2.p { |p| p << "&nbsp;" } # placeholder
16
+ end
17
+ section_break(body)
18
+ end
19
+
20
+ def make_body3(body, docxml)
21
+ body.div **{ class: "WordSection3" } do |div3|
22
+ middle docxml, div3
23
+ footnotes div3
24
+ comments div3
25
+ end
26
+ end
27
+
28
+ def insert_tab(out, n)
29
+ out.span **attr_code(style: "mso-tab-count:#{n}") do |span|
30
+ [1..n].each { span << "&#xA0; " }
31
+ end
32
+ end
33
+
34
+ def para_attrs(node)
35
+ classtype = nil
36
+ classtype = "Note" if @note
37
+ classtype = "MsoCommentText" if in_comment
38
+ classtype = "Sourcecode" if @annotation
39
+ attrs = { class: classtype, id: node["id"] }
40
+ unless node["align"].nil?
41
+ attrs[:align] = node["align"] unless node["align"] == "justify"
42
+ attrs[:style] = "text-align:#{node['align']}"
43
+ end
44
+ attrs
45
+ end
46
+
47
+ def remove_bottom_border(td)
48
+ td["style"] =
49
+ td["style"].gsub(/border-bottom:[^;]+;/, "border-bottom:0pt;").
50
+ gsub(/mso-border-bottom-alt:[^;]+;/, "mso-border-bottom-alt:0pt;")
51
+ end
52
+
53
+ SW1 = "solid windowtext".freeze
54
+
55
+ def new_fullcolspan_row(t, tfoot)
56
+ # how many columns in the table?
57
+ cols = 0
58
+ t.at(".//tr").xpath("./td | ./th").each do |td|
59
+ cols += (td["colspan"] ? td["colspan"].to_i : 1)
60
+ end
61
+ style = %{border-top:0pt;mso-border-top-alt:0pt;border-bottom:#{SW1} 1.5pt;mso-border-bottom-alt:#{SW1} 1.5pt;}
62
+ tfoot.add_child("<tr><td colspan='#{cols}' style='#{style}'/></tr>")
63
+ tfoot.xpath(".//td").last
64
+ end
65
+
66
+ def make_tr_attr(td, row, totalrows)
67
+ style = td.name == "th" ? "font-weight:bold;" : ""
68
+ rowmax = td["rowspan"] ? row + td["rowspan"].to_i - 1 : row
69
+ style += <<~STYLE
70
+ border-top:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
71
+ mso-border-top-alt:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
72
+ border-bottom:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
73
+ mso-border-bottom-alt:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
74
+ STYLE
75
+ { rowspan: td["rowspan"], colspan: td["colspan"],
76
+ align: td["align"], style: style.gsub(/\n/, "") }
77
+ end
78
+
79
+ def section_break(body)
80
+ body.br **{ clear: "all", class: "section" }
81
+ end
82
+
83
+ def page_break(out)
84
+ out.br **{ clear: "all",
85
+ style: "mso-special-character:line-break;page-break-before:always" }
86
+ end
87
+
88
+ WORD_DT_ATTRS = {class: @note ? "Note" : nil, align: "left",
89
+ style: "margin-left:0pt;text-align:left;"}.freeze
90
+
91
+ def dt_parse(dt, term)
92
+ term.p **attr_code(WORD_DT_ATTRS) do |p|
93
+ if dt.elements.empty?
94
+ p << dt.text
95
+ else
96
+ dt.children.each { |n| parse(n, p) }
97
+ end
98
+ end
99
+ end
100
+
101
+ def dl_parse(node, out)
102
+ out.table **{ class: "dl" } do |v|
103
+ node.elements.select { |n| dt_dd? n }.each_slice(2) do |dt, dd|
104
+ v.tr do |tr|
105
+ tr.td **{ valign: "top", align: "left" } do |term|
106
+ dt_parse(dt, term)
107
+ end
108
+ tr.td **{ valign: "top" } do |listitem|
109
+ dd.children.each { |n| parse(n, listitem) }
110
+ end
111
+ end
112
+ end
113
+ dl_parse_notes(node, v)
114
+ end
115
+ end
116
+
117
+ def dl_parse_notes(node, v)
118
+ return if node.elements.reject { |n| dt_dd? n }.empty?
119
+ v.tr do |tr|
120
+ tr.td **{ rowspan: 2 } do |td|
121
+ node.elements.reject { |n| dt_dd? n }.each { |n| parse(n, td) }
122
+ end
123
+ end
124
+ end
125
+
126
+ def figure_get_or_make_dl(t)
127
+ dl = t.at(".//table[@class = 'dl']")
128
+ if dl.nil?
129
+ t.add_child("<p><b>#{@key_lbl}</b></p><table class='dl'></table>")
130
+ dl = t.at(".//table[@class = 'dl']")
131
+ end
132
+ dl
133
+ end
134
+
135
+ def figure_aside_process(f, aside, key)
136
+ # get rid of footnote link, it is in diagram
137
+ f&.at("./a[@class='TableFootnoteRef']")&.remove
138
+ fnref = f.at(".//a[@class='TableFootnoteRef']")
139
+ tr = key.add_child("<tr></tr>").first
140
+ dt = tr.add_child("<td valign='top' align='left'></td>").first
141
+ dd = tr.add_child("<td valign='top'></td>").first
142
+ fnref.parent = dt
143
+ aside.xpath(".//p").each do |a|
144
+ a.delete("class")
145
+ a.parent = dd
146
+ end
147
+ end
148
+ end
149
+ end
@@ -1,5 +1,5 @@
1
- module IsoDoc
2
- class WordConvert < Common
1
+ module IsoDoc::WordFunction
2
+ module Comments
3
3
 
4
4
  def in_comment
5
5
  @in_comment
@@ -0,0 +1,81 @@
1
+ module IsoDoc::WordFunction
2
+ module Footnotes
3
+
4
+ def footnotes(div)
5
+ return if @footnotes.empty?
6
+ @footnotes.each { |fn| div.parent << fn }
7
+ end
8
+
9
+ def make_table_footnote_link(out, fnid, fnref)
10
+ attrs = { href: "##{fnid}", class: "TableFootnoteRef" }
11
+ out.a **attrs do |a|
12
+ a << fnref
13
+ end
14
+ end
15
+
16
+ def make_table_footnote_target(out, fnid, fnref)
17
+ attrs = { id: fnid, class: "TableFootnoteRef" }
18
+ out.a **attrs do |a|
19
+ a << fnref
20
+ insert_tab(a, 1)
21
+ end
22
+ end
23
+
24
+ def make_table_footnote_text(node, fnid, fnref)
25
+ attrs = { id: "ftn#{fnid}" }
26
+ noko do |xml|
27
+ xml.div **attr_code(attrs) do |div|
28
+ make_table_footnote_target(div, fnid, fnref)
29
+ node.children.each { |n| parse(n, div) }
30
+ end
31
+ end.join("\n")
32
+ end
33
+
34
+ def make_generic_footnote_text(node, fnid)
35
+ noko do |xml|
36
+ xml.aside **{ id: "ftn#{fnid}" } do |div|
37
+ node.children.each { |n| parse(n, div) }
38
+ end
39
+ end.join("\n")
40
+ end
41
+
42
+ def get_table_ancestor_id(node)
43
+ table = node.ancestors("table") || node.ancestors("figure")
44
+ return UUIDTools::UUID.random_create.to_s if table.empty?
45
+ table.last["id"]
46
+ end
47
+
48
+ def table_footnote_parse(node, out)
49
+ fn = node["reference"]
50
+ tid = get_table_ancestor_id(node)
51
+ make_table_footnote_link(out, tid + fn, fn)
52
+ # do not output footnote text if we have already seen it for this table
53
+ return if @seen_footnote.include?(tid + fn)
54
+ @in_footnote = true
55
+ out.aside { |a| a << make_table_footnote_text(node, tid + fn, fn) }
56
+ @in_footnote = false
57
+ @seen_footnote << (tid + fn)
58
+ end
59
+
60
+ def footnote_parse(node, out)
61
+ return table_footnote_parse(node, out) if @in_table || @in_figure
62
+ fn = node["reference"]
63
+ out.a **{ "epub:type": "footnote", href: "#ftn#{fn}" } do |a|
64
+ a.sup { |sup| sup << fn }
65
+ end
66
+ return if @seen_footnote.include?(fn)
67
+ @in_footnote = true
68
+ @footnotes << make_generic_footnote_text(node, fn)
69
+ @in_footnote = false
70
+ @seen_footnote << fn
71
+ end
72
+
73
+ def make_footnote(node, fn)
74
+ return if @seen_footnote.include?(fn)
75
+ @in_footnote = true
76
+ @footnotes << make_generic_footnote_text(node, fn)
77
+ @in_footnote = false
78
+ @seen_footnote << fn
79
+ end
80
+ end
81
+ end