isodoc 2.4.0 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/isodoc.gemspec +1 -0
  3. data/lib/isodoc/base_style/all.css +29 -0
  4. data/lib/isodoc/base_style/metanorma_word.css +9 -0
  5. data/lib/isodoc/base_style/metanorma_word.scss +11 -0
  6. data/lib/isodoc/base_style/reset.css +29 -0
  7. data/lib/isodoc/base_style/reset.scss +34 -0
  8. data/lib/isodoc/base_style/rouge.css +39 -0
  9. data/lib/isodoc/base_style/typography.scss +6 -3
  10. data/lib/isodoc/convert.rb +7 -4
  11. data/lib/isodoc/function/blocks.rb +26 -16
  12. data/lib/isodoc/function/inline.rb +17 -17
  13. data/lib/isodoc/function/references.rb +38 -52
  14. data/lib/isodoc/function/table.rb +22 -13
  15. data/lib/isodoc/function/to_word_html.rb +1 -4
  16. data/lib/isodoc/function/utils.rb +5 -1
  17. data/lib/isodoc/html_function/html.rb +13 -34
  18. data/lib/isodoc/html_function/postprocess.rb +14 -1
  19. data/lib/isodoc/html_function/postprocess_cover.rb +6 -9
  20. data/lib/isodoc/metadata.rb +5 -0
  21. data/lib/isodoc/presentation_function/block.rb +15 -46
  22. data/lib/isodoc/presentation_function/refs.rb +75 -3
  23. data/lib/isodoc/presentation_function/sourcecode.rb +114 -0
  24. data/lib/isodoc/presentation_function/terms.rb +29 -37
  25. data/lib/isodoc/presentation_function/xrefs.rb +9 -6
  26. data/lib/isodoc/version.rb +1 -1
  27. data/lib/isodoc/word_function/body.rb +16 -16
  28. data/lib/isodoc/word_function/postprocess.rb +47 -43
  29. data/lib/isodoc/word_function/postprocess_cover.rb +29 -157
  30. data/lib/isodoc/word_function/postprocess_toc.rb +165 -0
  31. data/lib/isodoc/word_function/table.rb +25 -13
  32. data/lib/isodoc/xref/xref_gen.rb +2 -4
  33. metadata +19 -2
@@ -13,7 +13,7 @@ module IsoDoc
13
13
  if thead
14
14
  table.thead do |h|
15
15
  thead.element_children.each_with_index do |n, i|
16
- tr_parse(n, h, i, thead.element_children.size, true)
16
+ tr_parse(n, h, i, thead.xpath(ns("./tr")).size, true)
17
17
  end
18
18
  end
19
19
  end
@@ -23,7 +23,7 @@ module IsoDoc
23
23
  tbody = node.at(ns("./tbody")) || return
24
24
  table.tbody do |h|
25
25
  tbody.element_children.each_with_index do |n, i|
26
- tr_parse(n, h, i, tbody.element_children.size, false)
26
+ tr_parse(n, h, i, tbody.xpath(ns("./tr")).size, false)
27
27
  end
28
28
  end
29
29
  end
@@ -33,7 +33,7 @@ module IsoDoc
33
33
  if tfoot
34
34
  table.tfoot do |h|
35
35
  tfoot.element_children.each_with_index do |n, i|
36
- tr_parse(n, h, i, tfoot.element_children.size, false)
36
+ tr_parse(n, h, i, tfoot.xpath(ns("./tr")).size, false)
37
37
  end
38
38
  end
39
39
  end
@@ -41,11 +41,13 @@ module IsoDoc
41
41
 
42
42
  def table_attrs(node)
43
43
  width = node["width"] ? "width:#{node['width']};" : nil
44
+ c = node["class"]
45
+ bordered = "border-width:1px;border-spacing:0;"
46
+ (%w(modspec).include?(c) || !c) or bordered = ""
44
47
  attr_code(
45
48
  id: node["id"],
46
- class: node["class"] || "MsoISOTable",
47
- style: "border-width:1px;border-spacing:0;"\
48
- "#{width}#{keep_style(node)}",
49
+ class: c || "MsoISOTable",
50
+ style: "#{bordered}#{width}#{keep_style(node)}",
49
51
  title: node["alt"],
50
52
  )
51
53
  end
@@ -91,26 +93,33 @@ module IsoDoc
91
93
  # border-left:#{col.zero? ? "#{SW} 1.5pt;" : "none;"}
92
94
  # border-right:#{SW} #{col == totalcols && !header ? "1.5" : "1.0"}pt;
93
95
 
94
- def make_tr_attr(cell, row, totalrows, header)
96
+ def make_tr_attr(cell, row, totalrows, header, bordered)
95
97
  style = cell.name == "th" ? "font-weight:bold;" : ""
96
98
  cell["align"] and style += "text-align:#{cell['align']};"
97
99
  cell["valign"] and style += "vertical-align:#{cell['valign']};"
98
100
  rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
99
- style += <<~STYLE
100
- border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
101
- border-bottom:#{SW} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
102
- STYLE
101
+ style += make_tr_attr_style(row, rowmax, totalrows, header, bordered)
103
102
  header and scope = (cell["colspan"] ? "colgroup" : "col")
104
103
  !header && cell.name == "th" and
105
104
  scope = (cell["rowspan"] ? "rowgroup" : "row")
106
105
  { rowspan: cell["rowspan"], colspan: cell["colspan"],
107
- style: style.gsub(/\n/, ""), scope: scope }
106
+ style: style.gsub(/\n/, ""), scope: scope, class: cell["class"] }
107
+ end
108
+
109
+ def make_tr_attr_style(row, rowmax, totalrows, _header, bordered)
110
+ bordered or return ""
111
+ <<~STYLE.gsub(/\n/, "")
112
+ border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
113
+ border-bottom:#{SW} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;
114
+ STYLE
108
115
  end
109
116
 
110
117
  def tr_parse(node, out, ord, totalrows, header)
118
+ c = node.parent.parent["class"]
119
+ bordered = %w(modspec).include?(c) || !c
111
120
  out.tr do |r|
112
121
  node.elements.each do |td|
113
- attrs = make_tr_attr(td, ord, totalrows - 1, header)
122
+ attrs = make_tr_attr(td, ord, totalrows - 1, header, bordered)
114
123
  r.send td.name, **attr_code(attrs) do |entry|
115
124
  td.children.each { |n| parse(n, entry) }
116
125
  end
@@ -8,10 +8,6 @@ module IsoDoc
8
8
  @termdomain = termdomain
9
9
  end
10
10
 
11
- def in_sourcecode
12
- @sourcecode
13
- end
14
-
15
11
  def note?
16
12
  @note
17
13
  end
@@ -101,6 +97,7 @@ module IsoDoc
101
97
  end
102
98
 
103
99
  def info(isoxml, out)
100
+ @meta.code_css isoxml, out
104
101
  @meta.title isoxml, out
105
102
  @meta.subtitle isoxml, out
106
103
  @meta.docstatus isoxml, out
@@ -37,10 +37,14 @@ module IsoDoc
37
37
  DOCTYPE_HDR = "<!DOCTYPE html SYSTEM " \
38
38
  '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
39
39
 
40
+ HUGESTRICT =
41
+ Nokogiri::XML::ParseOptions::HUGE |
42
+ Nokogiri::XML::ParseOptions::STRICT
43
+
40
44
  def to_xhtml(xml)
41
45
  xml = to_xhtml_prep(xml)
42
46
  begin
43
- Nokogiri::XML.parse(xml, &:strict)
47
+ Nokogiri::XML.parse(xml, nil, nil, HUGESTRICT)
44
48
  rescue Nokogiri::XML::SyntaxError => e
45
49
  File.open("#{@filename}.#{@format}.err", "w:UTF-8") do |f|
46
50
  f.write xml
@@ -7,7 +7,7 @@ module IsoDoc
7
7
  def convert1(docxml, filename, dir)
8
8
  bibitem_lookup(docxml)
9
9
  noko do |xml|
10
- xml.html **{ lang: @lang.to_s } do |html|
10
+ xml.html lang: @lang.to_s do |html|
11
11
  info docxml, nil
12
12
  populate_css
13
13
  html.head { |head| define_head head, filename, dir }
@@ -19,7 +19,7 @@ module IsoDoc
19
19
  def make_body1(body, _docxml)
20
20
  return if @bare
21
21
 
22
- body.div **{ class: "title-section" } do |div1|
22
+ body.div class: "title-section" do |div1|
23
23
  div1.p { |p| p << "&#xa0;" } # placeholder
24
24
  end
25
25
  section_break(body)
@@ -28,14 +28,14 @@ module IsoDoc
28
28
  def make_body2(body, _docxml)
29
29
  return if @bare
30
30
 
31
- body.div **{ class: "prefatory-section" } do |div2|
31
+ body.div class: "prefatory-section" do |div2|
32
32
  div2.p { |p| p << "&#xa0;" } # placeholder
33
33
  end
34
34
  section_break(body)
35
35
  end
36
36
 
37
37
  def make_body3(body, docxml)
38
- body.div **{ class: "main-section" } do |div3|
38
+ body.div class: "main-section" do |div3|
39
39
  boilerplate docxml, div3
40
40
  preface_block docxml, div3
41
41
  abstract docxml, div3
@@ -51,8 +51,8 @@ module IsoDoc
51
51
 
52
52
  def googlefonts
53
53
  <<~HEAD.freeze
54
- <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
55
- <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,900" rel="stylesheet">
54
+ <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet"/>
55
+ <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,900" rel="stylesheet"/>
56
56
  HEAD
57
57
  end
58
58
 
@@ -66,11 +66,11 @@ module IsoDoc
66
66
  <script type="text/javascript">#{toclevel}</script>
67
67
 
68
68
  <!--Google fonts-->
69
- <link rel="preconnect" href="https://fonts.gstatic.com">#{' '}
69
+ <link rel="preconnect" href="https://fonts.gstatic.com"/>
70
70
  #{googlefonts}
71
71
  <!--Font awesome import for the link icon-->
72
- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
73
- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous">
72
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous"/>
73
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous"/>
74
74
  <style class="anchorjs"></style>
75
75
  HEAD
76
76
  end
@@ -89,33 +89,12 @@ module IsoDoc
89
89
  d.children.empty? or d.children.first.previous = html_button
90
90
  end
91
91
 
92
- def sourcecodelang(lang)
93
- return unless lang
94
-
95
- case lang.downcase
96
- when "javascript" then "lang-js"
97
- when "c" then "lang-c"
98
- when "c+" then "lang-cpp"
99
- when "console" then "lang-bsh"
100
- when "ruby" then "lang-rb"
101
- when "html" then "lang-html"
102
- when "java" then "lang-java"
103
- when "xml" then "lang-xml"
104
- when "perl" then "lang-perl"
105
- when "python" then "lang-py"
106
- when "xsl" then "lang-xsl"
107
- else
108
- ""
109
- end
110
- end
111
-
112
92
  def sourcecode_parse(node, out)
113
93
  name = node.at(ns("./name"))
114
- class1 = "prettyprint #{sourcecodelang(node&.at(ns('./@lang'))&.value)}"
115
- out.pre **sourcecode_attrs(node).merge(class: class1) do |div|
116
- @sourcecode = true
117
- node.children.each { |n| parse(n, div) unless n.name == "name" }
118
- @sourcecode = false
94
+ tag = node.at(ns(".//sourcecode | .//table")) ? "div" : "pre"
95
+ attr = sourcecode_attrs(node).merge(class: "sourcecode")
96
+ out.send tag, **attr do |div|
97
+ sourcecode_parse1(node, div)
119
98
  end
120
99
  sourcecode_name_parse(node, out, name)
121
100
  end
@@ -27,7 +27,20 @@ module IsoDoc
27
27
  def html_cleanup(html)
28
28
  html = term_header(html_footnote_filter(html_preface(htmlstyle(html))))
29
29
  html = footnote_format(footnote_backlinks(html_toc(html)))
30
- mathml(html_list_clean(remove_placeholder_paras(html)))
30
+ html = mathml(html_list_clean(remove_placeholder_paras(html)))
31
+ sourcecode_cleanup(html)
32
+ end
33
+
34
+ def sourcecode_cleanup(html)
35
+ ann = ".//div[@class = 'annotation']"
36
+ html.xpath("//pre[#{ann}] | //div[@class = 'sourcecode'][#{ann}]")
37
+ .each do |p|
38
+ ins = p.after("<pre class='sourcecode'/>").next_element
39
+ p.xpath(ann).each do |d|
40
+ ins << d.remove.children
41
+ end
42
+ end
43
+ html
31
44
  end
32
45
 
33
46
  def remove_placeholder_paras(html)
@@ -31,6 +31,9 @@ module IsoDoc
31
31
  head = docxml.at("//*[local-name() = 'head']")
32
32
  head << htmlstylesheet(@htmlstylesheet)
33
33
  s = htmlstylesheet(@htmlstylesheet_override) and head << s
34
+ s = @meta.get[:code_css] and
35
+ head << "<style><!--#{s.gsub(/sourcecode/,
36
+ 'pre.sourcecode')}--></style>"
34
37
  @bare and
35
38
  head << "<style>body {margin-left: 2em; margin-right: 2em;}</style>"
36
39
  docxml
@@ -40,7 +43,6 @@ module IsoDoc
40
43
  html_cover(docxml) if @htmlcoverpage && !@bare
41
44
  html_intro(docxml) if @htmlintropage && !@bare
42
45
  docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
43
- docxml.at("//body") << sourcecode_highlighter
44
46
  html_main(docxml)
45
47
  authority_cleanup(docxml)
46
48
  docxml
@@ -48,7 +50,7 @@ module IsoDoc
48
50
 
49
51
  def authority_cleanup1(docxml, klass)
50
52
  dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
51
- auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or "\
53
+ auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or " \
52
54
  "@class = 'boilerplate-#{klass}']")
53
55
  auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each(&:remove)
54
56
  auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
@@ -92,7 +94,7 @@ module IsoDoc
92
94
  end
93
95
 
94
96
  def html_toc_entry(level, header)
95
- content = header.at("./following-sibling::p"\
97
+ content = header.at("./following-sibling::p" \
96
98
  "[@class = 'variant-title-toc']") || header
97
99
  %(<li class="#{level}"><a href="##{header['id']}">\
98
100
  #{header_strip(content)}</a></li>)
@@ -127,7 +129,7 @@ module IsoDoc
127
129
  end
128
130
 
129
131
  def toc_exclude_class
130
- "[not(@class = 'TermNum')][not(@class = 'noTOC')]"\
132
+ "[not(@class = 'TermNum')][not(@class = 'noTOC')]" \
131
133
  "[string-length(normalize-space(.))>0]"
132
134
  end
133
135
 
@@ -142,11 +144,6 @@ module IsoDoc
142
144
  "#{a[0]}#{scripts}#{scripts_override}</body>#{a[1]}"
143
145
  end
144
146
 
145
- def sourcecode_highlighter
146
- '<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
147
- 'loader/run_prettify.js"></script>'
148
- end
149
-
150
147
  MATHJAX_ADDR =
151
148
  "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
152
149
  MATHJAX = <<~"MATHJAX".freeze
@@ -168,5 +168,10 @@ module IsoDoc
168
168
  end
169
169
  set(:title_footnote, ret)
170
170
  end
171
+
172
+ def code_css(isoxml, _out)
173
+ c = isoxml.at(ns("//misc-container/source-highlighter-css")) or return
174
+ set(:code_css, c.text)
175
+ end
171
176
  end
172
177
  end
@@ -1,4 +1,6 @@
1
1
  require_relative "./image"
2
+ require_relative "./sourcecode"
3
+ require "rouge"
2
4
 
3
5
  module IsoDoc
4
6
  class PresentationXMLConvert < ::IsoDoc::Convert
@@ -25,24 +27,8 @@ module IsoDoc
25
27
  end
26
28
  end
27
29
 
28
- def sourcecode(docxml)
29
- docxml.xpath(ns("//sourcecode")).each do |f|
30
- sourcecode1(f)
31
- end
32
- end
33
-
34
- def sourcecode1(elem)
35
- return if labelled_ancestor(elem)
36
-
37
- lbl = @xrefs.anchor(elem["id"], :label, false) or return
38
- prefix_name(elem, block_delim,
39
- l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
40
- end
41
-
42
30
  def formula(docxml)
43
- docxml.xpath(ns("//formula")).each do |f|
44
- formula1(f)
45
- end
31
+ docxml.xpath(ns("//formula")).each { |f| formula1(f) }
46
32
  end
47
33
 
48
34
  def formula1(elem)
@@ -51,48 +37,38 @@ module IsoDoc
51
37
  end
52
38
 
53
39
  def example(docxml)
54
- docxml.xpath(ns("//example")).each do |f|
55
- example1(f)
56
- end
40
+ docxml.xpath(ns("//example")).each { |f| example1(f) }
57
41
  end
58
42
 
59
43
  def example1(elem)
60
44
  n = @xrefs.get[elem["id"]]
61
45
  lbl = if n.nil? || n[:label].nil? || n[:label].empty?
62
46
  @i18n.example
63
- else
64
- l10n("#{@i18n.example} #{n[:label]}")
47
+ else l10n("#{@i18n.example} #{n[:label]}")
65
48
  end
66
49
  prefix_name(elem, block_delim, lbl, "name")
67
50
  end
68
51
 
69
52
  def note(docxml)
70
- docxml.xpath(ns("//note")).each do |f|
71
- note1(f)
72
- end
53
+ docxml.xpath(ns("//note")).each { |f| note1(f) }
73
54
  end
74
55
 
75
56
  def note1(elem)
76
- return if elem.parent.name == "bibitem" || elem["notag"] == "true"
77
-
57
+ elem.parent.name == "bibitem" || elem["notag"] == "true" and return
78
58
  n = @xrefs.get[elem["id"]]
79
59
  lbl = if n.nil? || n[:label].nil? || n[:label].empty?
80
60
  @i18n.note
81
- else
82
- l10n("#{@i18n.note} #{n[:label]}")
61
+ else l10n("#{@i18n.note} #{n[:label]}")
83
62
  end
84
63
  prefix_name(elem, "", lbl, "name")
85
64
  end
86
65
 
87
66
  def admonition(docxml)
88
- docxml.xpath(ns("//admonition")).each do |f|
89
- admonition1(f)
90
- end
67
+ docxml.xpath(ns("//admonition")).each { |f| admonition1(f) }
91
68
  end
92
69
 
93
70
  def admonition1(elem)
94
- return if elem.at(ns("./name")) || elem["notag"] == "true"
95
-
71
+ elem.at(ns("./name")) || elem["notag"] == "true" and return
96
72
  prefix_name(elem, "", @i18n.admonition[elem["type"]]&.upcase, "name")
97
73
  end
98
74
 
@@ -121,15 +97,12 @@ module IsoDoc
121
97
  end
122
98
 
123
99
  def table(docxml)
124
- docxml.xpath(ns("//table")).each do |f|
125
- table1(f)
126
- end
100
+ docxml.xpath(ns("//table")).each { |f| table1(f) }
127
101
  end
128
102
 
129
103
  def table1(elem)
130
- return if labelled_ancestor(elem)
131
- return if elem["unnumbered"] && !elem.at(ns("./name"))
132
-
104
+ labelled_ancestor(elem) and return
105
+ elem["unnumbered"] && !elem.at(ns("./name")) and return
133
106
  n = @xrefs.anchor(elem["id"], :label, false)
134
107
  prefix_name(elem, block_delim, l10n("#{lower2cap @i18n.table} #{n}"),
135
108
  "name")
@@ -137,9 +110,7 @@ module IsoDoc
137
110
 
138
111
  # we use this to eliminate the semantic amend blocks from rendering
139
112
  def amend(docxml)
140
- docxml.xpath(ns("//amend")).each do |f|
141
- amend1(f)
142
- end
113
+ docxml.xpath(ns("//amend")).each { |f| amend1(f) }
143
114
  end
144
115
 
145
116
  def amend1(elem)
@@ -150,9 +121,7 @@ module IsoDoc
150
121
  end
151
122
 
152
123
  def ol(docxml)
153
- docxml.xpath(ns("//ol")).each do |f|
154
- ol1(f)
155
- end
124
+ docxml.xpath(ns("//ol")).each { |f| ol1(f) }
156
125
  @xrefs.list_anchor_names(docxml.xpath(ns(@xrefs.sections_xpath)))
157
126
  end
158
127
 
@@ -49,8 +49,8 @@ module IsoDoc
49
49
  def bibrender_relaton(xml, renderings)
50
50
  f = renderings[xml["id"]][:formattedref]
51
51
  f &&= "<formattedref>#{f}</formattedref>"
52
- xml.children =
53
- "#{f}#{xml.xpath(ns('./docidentifier | ./uri | ./note')).to_xml}"
52
+ x = xml.xpath(ns("./docidentifier | ./uri | ./note | ./biblio-tag"))
53
+ xml.children = "#{f}#{x.to_xml}"
54
54
  end
55
55
 
56
56
  def bibrenderer
@@ -74,6 +74,7 @@ module IsoDoc
74
74
  i = bibliography_bibitem_number1(b, i)
75
75
  end
76
76
  @xrefs.references docxml
77
+ bibliography_bibitem_tag(docxml)
77
78
  end
78
79
 
79
80
  def bibliography_bibitem_number1(bibitem, idx)
@@ -99,8 +100,79 @@ module IsoDoc
99
100
 
100
101
  def docid_prefixes(docxml)
101
102
  docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
102
- i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
103
+ i.children = @xrefs.klass.docid_prefix(i["type"], to_xml(i.children))
103
104
  end
104
105
  end
106
+
107
+ def bibliography_bibitem_tag(docxml)
108
+ [true, false].each do |norm|
109
+ i = 0
110
+ docxml.xpath(ns("//references[@normative = '#{norm}']")).each do |r|
111
+ i = bibliography_bibitem_tag1(r, i, norm)
112
+ end
113
+ end
114
+ end
115
+
116
+ def bibliography_bibitem_tag1(ref, idx, norm)
117
+ ref.xpath(ns("./bibitem")).each do |b|
118
+ @xrefs.klass.implicit_reference(b) and next
119
+ idx += 1 unless b["hidden"]
120
+ insert_biblio_tag(b, idx, !norm, @xrefs.klass.standard?(b))
121
+ end
122
+ idx
123
+ end
124
+
125
+ def insert_biblio_tag(bib, ordinal, biblio, standard)
126
+ datefn = date_note_process(bib)
127
+ ids = @xrefs.klass.bibitem_ref_code(bib)
128
+ idents = @xrefs.klass.render_identifier(ids)
129
+ ret = if biblio then biblio_ref_entry_code(ordinal, idents, ids,
130
+ standard, datefn)
131
+ else norm_ref_entry_code(ordinal, idents, ids, standard, datefn)
132
+ end
133
+ bib << "<biblio-tag>#{ret}</biblio-tag>"
134
+ end
135
+
136
+ def norm_ref_entry_code(_ordinal, idents, _ids, _standard, datefn)
137
+ ret = (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
138
+ (idents[:ordinal] || idents[:metanorma]) && idents[:sdo] and
139
+ ret += ", #{idents[:sdo]}"
140
+ ret += datefn
141
+ ret.empty? and return ret
142
+ idents[:sdo] and ret += ","
143
+ "#{ret} "
144
+ end
145
+
146
+ # if ids is just a number, only use that ([1] Non-Standard)
147
+ # else, use both ordinal, as prefix, and ids
148
+ def biblio_ref_entry_code(ordinal, ids, _id, standard, datefn)
149
+ standard and id = nil
150
+ ret = (ids[:ordinal] || ids[:metanorma] || "[#{ordinal}]")
151
+ if ids[:sdo]
152
+ ret = prefix_bracketed_ref(ret)
153
+ ret += "#{ids[:sdo]}#{datefn}, "
154
+ else
155
+ ret = prefix_bracketed_ref("#{ret}#{datefn}")
156
+ end
157
+ ret
158
+ end
159
+
160
+ def prefix_bracketed_ref(text)
161
+ "#{text}<tab/>"
162
+ end
163
+
164
+ # strip any fns in docidentifier before they are extracted for rendering
165
+ def date_note_process(bib)
166
+ ret = ident_fn(bib)
167
+ date_note = bib.at(ns("./note[@type = 'Unpublished-Status']"))
168
+ date_note.nil? and return ret
169
+ id = UUIDTools::UUID.random_create.to_s
170
+ "#{ret}<fn reference='#{id}'><p>#{date_note.content}</p></fn>"
171
+ end
172
+
173
+ def ident_fn(bib)
174
+ ret = bib.at(ns("./docidentifier//fn")) or return ""
175
+ to_xml(ret.remove)
176
+ end
105
177
  end
106
178
  end
@@ -0,0 +1,114 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def sourcehighlighter_css(docxml)
4
+ @sourcehighlighter or return
5
+ ins = docxml.at(ns("//misc-container")) ||
6
+ docxml.at(ns("//bibdata")).after("<misc-container/>").next_element
7
+ ins << "<source-highlighter-css>#{sourcehighlighter_css_file}" \
8
+ "</source-highlighter-css>"
9
+ end
10
+
11
+ def sourcehighlighter_css_file
12
+ File.read(File.join(File.dirname(__FILE__), "..", "base_style",
13
+ "rouge.css"))
14
+ end
15
+
16
+ def sourcehighlighter
17
+ @sourcehighlighter or return
18
+ f = Rouge::Formatters::HTML.new
19
+ opts = { gutter_class: "rouge-gutter", code_class: "rouge-code" }
20
+ { formatter: f,
21
+ formatter_line: Rouge::Formatters::HTMLLineTable.new(f, opts) }
22
+ end
23
+
24
+ def sourcecode(docxml)
25
+ sourcehighlighter_css(docxml)
26
+ @highlighter = sourcehighlighter
27
+ docxml.xpath(ns("//sourcecode")).each do |f|
28
+ sourcecode1(f)
29
+ end
30
+ end
31
+
32
+ def sourcecode1(elem)
33
+ source_highlight(elem)
34
+ source_label(elem)
35
+ end
36
+
37
+ def source_highlight(elem)
38
+ @highlighter or return
39
+ markup = source_remove_markup(elem)
40
+ p = source_lex(elem)
41
+ elem.children = if elem["linenums"] == "true"
42
+ r = sourcecode_table_to_elem(elem, p)
43
+ source_restore_markup_table(r, markup)
44
+ else
45
+ r = @highlighter[:formatter].format(p)
46
+ source_restore_markup(Nokogiri::XML.fragment(r), markup)
47
+ end
48
+ end
49
+
50
+ def source_remove_markup(elem)
51
+ ret = {}
52
+ name = elem.at(ns("./name")) and ret[:name] = name.remove.to_xml
53
+ ret[:ann] = elem.xpath(ns("./annotation")).each(&:remove)
54
+ ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
55
+ m << { xml: c.remove.to_xml, line: c.line - elem.line }
56
+ end
57
+ ret
58
+ end
59
+
60
+ def source_restore_markup(wrapper, markup)
61
+ ret = source_restore_callouts(wrapper, markup[:call])
62
+ "#{markup[:name]}#{ret}#{markup[:ann]}"
63
+ end
64
+
65
+ def source_restore_markup_table(wrapper, markup)
66
+ source_restore_callouts_table(wrapper, markup[:call])
67
+ ret = to_xml(wrapper)
68
+ "#{markup[:name]}#{ret}#{markup[:ann]}"
69
+ end
70
+
71
+ def source_restore_callouts(code, callouts)
72
+ text = to_xml(code)
73
+ text.split(/[\n\r]/).each_with_index do |c, i|
74
+ while !callouts.empty? && callouts[0][:line] == i
75
+ c.sub!(/\s+$/, " <span class='c'>#{callouts[0][:xml]}</span> ")
76
+ callouts.shift
77
+ end
78
+ end.join("\n")
79
+ end
80
+
81
+ def source_restore_callouts_table(table, callouts)
82
+ table.xpath(".//td[@class = 'rouge-code']/sourcecode")
83
+ .each_with_index do |c, i|
84
+ while !callouts.empty? && callouts[0][:line] == i
85
+ c << " <span class='c'>#{callouts[0][:xml]}</span> "
86
+ callouts.shift
87
+ end
88
+ end
89
+ end
90
+
91
+ def sourcecode_table_to_elem(elem, tokens)
92
+ r = Nokogiri::XML(@highlighter[:formatter_line].format(tokens)).root
93
+ r.xpath(".//td[@class = 'rouge-code']/pre").each do |pre|
94
+ %w(style).each { |n| elem[n] and pre[n] = elem[n] }
95
+ pre.name = "sourcecode"
96
+ pre.children = to_xml(pre.children).sub(/\s+$/, "")
97
+ end
98
+ r
99
+ end
100
+
101
+ def source_lex(elem)
102
+ l = (Rouge::Lexer.find(elem["lang"] || "plaintext") ||
103
+ Rouge::Lexer.find("plaintext"))
104
+ l.lex(@c.decode(elem.children.to_xml))
105
+ end
106
+
107
+ def source_label(elem)
108
+ labelled_ancestor(elem) and return
109
+ lbl = @xrefs.anchor(elem["id"], :label, false) or return
110
+ prefix_name(elem, block_delim,
111
+ l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
112
+ end
113
+ end
114
+ end