isodoc 2.4.0 → 2.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a7c100c4751a8d8bfe69eeaf31614c74bfeec4c56d188fd0d4a6a16c09d3257
4
- data.tar.gz: '0858086207425a9c38bb6f12fba1a219599c4c7e469aea40e4f29255f152333b'
3
+ metadata.gz: ba10d3ff61b6c99d2251fd1d8e868bf09aea5dde1da505bc1745003778f8750d
4
+ data.tar.gz: b758cac0f031d6a16c95ba8dd05c963bf227438d64d63f1f3146dd745d5c42e9
5
5
  SHA512:
6
- metadata.gz: bc74e409e73b0b63f5a609e44b0a90a88cf4e83253604cbf6634f62b9c6ff12cccdc40fa2399acd4c373c44d3748ff311828890f319fc508c35e4993c88ff800
7
- data.tar.gz: b6f7d0abe389ee3c0342fbdd862f0671bc94959eb9f7b3755e51c7aac1aad74e65127b8819f5b3f310a8e2c2ede29dd663642f9a16e12b5fdf563dd9e2e9bb4f
6
+ metadata.gz: 1ba1187b3202d8b8ef7d8c0376ba6cd100230a0cbe889cfaa729510f174cdbfba884b2ca2b5607525b53391b83a007313e21427539aa8c42d604d295b90feb3b
7
+ data.tar.gz: 0b15b2d4bee5c08e2a0989eba6909d37827f67943eb8f0e86f9815f202ca7f408955b1905c7d041e32ae1433ddc1fa99e7fdecf4bf49c0174ee194731104135f
data/isodoc.gemspec CHANGED
@@ -43,6 +43,7 @@ Gem::Specification.new do |spec|
43
43
  spec.add_dependency "relaton-cli"
44
44
  spec.add_dependency "relaton-render", "~> 0.5.2"
45
45
  spec.add_dependency "roman-numerals"
46
+ spec.add_dependency "rouge", "~> 4.0"
46
47
  spec.add_dependency "thread_safe"
47
48
  spec.add_dependency "twitter_cldr", ">= 6.6.0"
48
49
  spec.add_dependency "uuidtools"
@@ -24,8 +24,11 @@
24
24
  background: $colorHighlightBg;
25
25
  box-shadow: 3px 0 0 $colorHighlightBg, -3px 0 0 $colorHighlightBg;
26
26
  }
27
- ::selection,
28
- ::-moz-selection {
27
+ *::selection {
28
+ background: $colorHighlightBg;
29
+ color: $colorHighlightFg;
30
+ }
31
+ *::-moz-selection {
29
32
  background: $colorHighlightBg;
30
33
  color: $colorHighlightFg;
31
34
  }
@@ -11,7 +11,8 @@ require "mn-requirements"
11
11
 
12
12
  module IsoDoc
13
13
  class Convert < ::IsoDoc::Common
14
- attr_accessor :options, :i18n, :meta, :xrefs, :reqt_models, :requirements_processor
14
+ attr_accessor :options, :i18n, :meta, :xrefs, :reqt_models,
15
+ :requirements_processor
15
16
 
16
17
  # htmlstylesheet: Generic stylesheet for HTML
17
18
  # htmlstylesheet_override: Override stylesheet for HTML
@@ -48,6 +49,7 @@ module IsoDoc
48
49
  # fonts: fontist fonts to install
49
50
  # fontlicenseagreement: fontist font license agreement
50
51
  # modspecidentifierbase: base prefix for any Modspec identifiers
52
+ # sourcehighlighter: whether to apply sourcecode highlighting
51
53
  def initialize(options) # rubocop:disable Lint/MissingSuper
52
54
  @options = options_preprocess(options)
53
55
  init_stylesheets(@options)
@@ -76,10 +78,11 @@ module IsoDoc
76
78
  @suppressheadingnumbers = options[:suppressheadingnumbers]
77
79
  @break_up_urls_in_tables = options[:breakupurlsintables]
78
80
  @sectionsplit = options[:sectionsplit] == "true"
79
- @suppressasciimathdup = options[:suppressasciimathdup] == "true"
81
+ @suppressasciimathdup = options[:suppressasciimathdup]
80
82
  @bare = options[:bare]
81
83
  @aligncrosselements = options[:aligncrosselements]
82
84
  @modspecidentifierbase = options[:modspecidentifierbase]
85
+ @sourcehighlighter = options[:sourcehighlighter]
83
86
  end
84
87
 
85
88
  def init_i18n(options)
@@ -207,7 +210,7 @@ module IsoDoc
207
210
  docxml.root.default_namespace = ""
208
211
  convert_i18n_init(docxml)
209
212
  metadata_init(@lang, @script, @locale, @i18n)
210
- xref_init(@lang, @script, self, @i18n, {locale: @locale})
213
+ xref_init(@lang, @script, self, @i18n, { locale: @locale })
211
214
  [docxml, filename, dir]
212
215
  end
213
216
 
@@ -235,7 +238,7 @@ module IsoDoc
235
238
  end
236
239
 
237
240
  def middle_clause(_docxml = nil)
238
- "//clause[parent::sections][not(@type = 'scope')]"\
241
+ "//clause[parent::sections][not(@type = 'scope')]" \
239
242
  "[not(descendant::terms)]"
240
243
  end
241
244
 
@@ -75,7 +75,7 @@ module IsoDoc
75
75
  def sourcecode_parse(node, out)
76
76
  name = node.at(ns("./name"))
77
77
  out.p **sourcecode_attrs(node) do |div|
78
- @sourcecode = true
78
+ @sourcecode = true unless node.at(ns(".//sourcecode"))
79
79
  node.children.each { |n| parse(n, div) unless n.name == "name" }
80
80
  @sourcecode = false
81
81
  end
@@ -17,12 +17,12 @@ module IsoDoc
17
17
  def location_parse(node, out); end
18
18
 
19
19
  def span_parse(node, out)
20
- if node["style"]
21
- out.span **{ style: node["style"] } do |s|
20
+ if node["style"] || node["class"]
21
+ out.span **attr_code(style: node["style"],
22
+ class: node["class"]) do |s|
22
23
  node.children.each { |n| parse(n, s) }
23
24
  end
24
- else
25
- node.children.each { |n| parse(n, out) }
25
+ else node.children.each { |n| parse(n, out) }
26
26
  end
27
27
  end
28
28
 
@@ -10,60 +10,59 @@ module IsoDoc
10
10
  text
11
11
  end
12
12
 
13
- def nonstd_bibitem(list, bib, ordinal, biblio)
13
+ def nonstd_bibitem(list, bib, _ordinal, biblio) # %%%
14
14
  list.p **attr_code(iso_bibitem_entry_attrs(bib, biblio)) do |ref|
15
- ids = bibitem_ref_code(bib)
16
- idents = render_identifier(ids)
17
- if biblio then ref_entry_code(ref, ordinal, idents, ids)
18
- else
19
- ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
20
- ref << ", #{idents[sdo]}" if idents[:ordinal] && idents[:sdo]
21
- end
22
- ref << "," if idents[:sdo]
23
- ref << " "
15
+ # ids = bibitem_ref_code(bib)
16
+ # idents = render_identifier(ids)
17
+ # if biblio then ref_entry_code(ref, ordinal, idents, ids)
18
+ # else
19
+ # ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
20
+ # ref << ", #{idents[sdo]}" if idents[:ordinal] && idents[:sdo]
21
+ # end
22
+ # ref << "," if idents[:sdo]
23
+ tag = bib.at(ns("./biblio-tag"))
24
+ tag&.children&.each { |n| parse(n, ref) }
24
25
  reference_format(bib, ref)
25
26
  end
26
27
  end
27
28
 
28
- def std_bibitem_entry(list, bib, ordinal, biblio)
29
+ def std_bibitem_entry(list, bib, _ordinal, biblio) # %%%
29
30
  list.p **attr_code(iso_bibitem_entry_attrs(bib, biblio)) do |ref|
30
- idents = render_identifier(bibitem_ref_code(bib))
31
- if biblio then ref_entry_code(ref, ordinal, idents, nil)
32
- else
33
- ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
34
- ref << ", #{idents[:sdo]}" if (idents[:ordinal] ||
35
- idents[:metanorma]) && idents[:sdo]
36
- end
37
- date_note_process(bib, ref)
38
- ref << "," if idents[:sdo]
39
- ref << " "
31
+ # idents = render_identifier(bibitem_ref_code(bib))
32
+ # if biblio then ref_entry_code(ref, ordinal, idents, nil)
33
+ # else
34
+ # ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
35
+ # ref << ", #{idents[:sdo]}" if (idents[:ordinal] ||
36
+ # idents[:metanorma]) && idents[:sdo]
37
+ # end
38
+ # date_note_process(bib, ref)
39
+ # ref << "," if idents[:sdo]
40
+ tag = bib.at(ns("./biblio-tag"))
41
+ tag&.children&.each { |n| parse(n, ref) }
40
42
  reference_format(bib, ref)
41
43
  end
42
44
  end
43
45
 
44
- # if ids is just a number, only use that ([1] Non-Standard)
45
- # else, use both ordinal, as prefix, and ids
46
- def ref_entry_code(ref, ordinal, ids, _id)
47
- prefix_bracketed_ref(ref, ids[:ordinal] || ids[:metanorma] ||
48
- "[#{ordinal}]")
49
- ids[:sdo] and ref << (ids[:sdo]).to_s
50
- end
46
+ # # if ids is just a number, only use that ([1] Non-Standard)
47
+ # # else, use both ordinal, as prefix, and ids
48
+ # def ref_entry_code(ref, ordinal, ids, _id) #%%%
49
+ # prefix_bracketed_ref(ref, ids[:ordinal] || ids[:metanorma] ||
50
+ # "[#{ordinal}]")
51
+ # ids[:sdo] and ref << (ids[:sdo]).to_s
52
+ # end
51
53
 
52
- def pref_ref_code(bib)
53
- return nil if bib["suppress_identifier"] == "true"
54
+ SKIP_DOCID = "@type = 'DOI' or @type = 'metanorma' or @type = 'ISSN' or " \
55
+ "@type = 'metanorma-ordinal' or @type = 'ISBN'".freeze
54
56
 
55
- ret = bib.xpath(ns("./docidentifier[@primary = 'true'][@language = '#{@lang}']"))
57
+ def pref_ref_code(bib)
58
+ bib["suppress_identifier"] == "true" and return nil
59
+ lang = "[@language = '#{@lang}']"
60
+ ret = bib.xpath(ns("./docidentifier[@primary = 'true']#{lang}"))
56
61
  ret.empty? and
57
62
  ret = bib.xpath(ns("./docidentifier[@primary = 'true']"))
58
63
  ret.empty? and
59
- ret = bib.at(ns(<<~XPATH,
60
- ./docidentifier[not(@type = 'DOI' or @type = 'metanorma' or @type = 'metanorma-ordinal' or @type = 'ISSN' or @type = 'ISBN')][@language = '#{@lang}']
61
- XPATH
62
- )) ||
63
- bib.at(ns(<<~XPATH,
64
- ./docidentifier[not(@type = 'DOI' or @type = 'metanorma' or @type = 'metanorma-ordinal' or @type = 'ISSN' or @type = 'ISBN')]
65
- XPATH
66
- ))
64
+ ret = bib.at(ns("./docidentifier[not(#{SKIP_DOCID})]#{lang}")) ||
65
+ bib.at(ns("./docidentifier[not(#{SKIP_DOCID})]"))
67
66
  ret
68
67
  end
69
68
 
@@ -123,14 +122,6 @@ module IsoDoc
123
122
  .include? prefix
124
123
  end
125
124
 
126
- def date_note_process(bib, ref)
127
- date_note = bib.at(ns("./note[@type = 'Unpublished-Status']"))
128
- return if date_note.nil?
129
-
130
- date_note.children = "<p>#{date_note.content}</p>"
131
- footnote_parse(date_note, ref)
132
- end
133
-
134
125
  def iso_bibitem_entry_attrs(bib, biblio)
135
126
  { id: bib["id"], class: biblio ? "Biblio" : "NormRef" }
136
127
  end
@@ -141,11 +132,6 @@ module IsoDoc
141
132
  bib["hidden"] == "true"
142
133
  end
143
134
 
144
- def prefix_bracketed_ref(ref, text)
145
- ref << text.to_s
146
- insert_tab(ref, 1)
147
- end
148
-
149
135
  def reference_format(bib, out)
150
136
  ftitle = bib.at(ns("./formattedref"))
151
137
  ftitle&.children&.each { |n| parse(n, out) }
@@ -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,15 +93,12 @@ 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")
@@ -107,10 +106,20 @@ module IsoDoc
107
106
  style: style.gsub(/\n/, ""), scope: scope }
108
107
  end
109
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
115
+ end
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
@@ -101,6 +101,7 @@ module IsoDoc
101
101
  end
102
102
 
103
103
  def info(isoxml, out)
104
+ @meta.code_css isoxml, out
104
105
  @meta.title isoxml, out
105
106
  @meta.subtitle isoxml, out
106
107
  @meta.docstatus isoxml, out
@@ -89,31 +89,10 @@ 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
94
+ out.pre **sourcecode_attrs(node).merge(class: "sourcecode") do |div|
95
+ @sourcecode = true unless node.at(ns(".//sourcecode"))
117
96
  node.children.each { |n| parse(n, div) unless n.name == "name" }
118
97
  @sourcecode = false
119
98
  end
@@ -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,5 @@
1
1
  require_relative "./image"
2
+ require "rouge"
2
3
 
3
4
  module IsoDoc
4
5
  class PresentationXMLConvert < ::IsoDoc::Convert
@@ -25,24 +26,106 @@ module IsoDoc
25
26
  end
26
27
  end
27
28
 
29
+ def sourcehighlighter_theme
30
+ "igorpro"
31
+ end
32
+
33
+ def sourcehighlighter_css(docxml)
34
+ @sourcehighlighter or return
35
+ ins = docxml.at(ns("//misc-container")) ||
36
+ docxml.at(ns("//bibdata")).after("<misc-container/>").next_element
37
+ x = Rouge::Theme.find(sourcehighlighter_theme)
38
+ .render(scope: "sourcecode")
39
+ ins << "<source-highlighter-css>#{x}</source-highlighter-css>"
40
+ end
41
+
42
+ def sourcehighlighter
43
+ @sourcehighlighter or return
44
+ f = Rouge::Formatters::HTML.new
45
+ { formatter: f,
46
+ formatter_line: Rouge::Formatters::HTMLTable.new(f, {}) }
47
+ end
48
+
28
49
  def sourcecode(docxml)
50
+ sourcehighlighter_css(docxml)
51
+ @highlighter = sourcehighlighter
29
52
  docxml.xpath(ns("//sourcecode")).each do |f|
30
53
  sourcecode1(f)
31
54
  end
32
55
  end
33
56
 
34
57
  def sourcecode1(elem)
35
- return if labelled_ancestor(elem)
58
+ source_highlight(elem)
59
+ source_label(elem)
60
+ end
61
+
62
+ def source_highlight(elem)
63
+ @highlighter or return
64
+ markup = source_remove_markup(elem)
65
+ p = source_lex(elem)
66
+ wrapper, code =
67
+ if elem["linenums"] == "true" then sourcecode_table_to_elem(elem, p)
68
+ else
69
+ r = Nokogiri::XML.fragment(@highlighter[:formatter].format(p))
70
+ [r, r]
71
+ end
72
+ elem.children = source_restore_markup(wrapper, code, markup)
73
+ end
74
+
75
+ def source_remove_markup(elem)
76
+ ret = {}
77
+ name = elem.at(ns("./name")) and ret[:name] = name.remove.to_xml
78
+ ret[:ann] = elem.xpath(ns("./annotation")).each(&:remove)
79
+ ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
80
+ m << { xml: c.remove.to_xml, line: c.line - elem.line }
81
+ end
82
+ ret
83
+ end
84
+
85
+ def source_restore_markup(wrapper, code, markup)
86
+ text = source_restore_callouts(code, markup[:call])
87
+ ret = if code == wrapper
88
+ text
89
+ else
90
+ code.replace(text)
91
+ to_xml(wrapper)
92
+ end
93
+ "#{markup[:name]}#{ret}#{markup[:ann]}"
94
+ end
95
+
96
+ def source_restore_callouts(code, callouts)
97
+ text = to_xml(code)
98
+ text.split(/[\n\r]/).each_with_index do |c, i|
99
+ while !callouts.empty? && callouts[0][:line] == i
100
+ c.sub!(/\s+$/, " #{callouts[0][:xml]} ")
101
+ callouts.shift
102
+ end
103
+ end.join("\n")
104
+ end
36
105
 
106
+ def sourcecode_table_to_elem(elem, tokens)
107
+ r = Nokogiri::XML(@highlighter[:formatter_line].format(tokens)).root
108
+ pre = r.at(".//td[@class = 'rouge-code']/pre")
109
+ %w(style).each { |n| elem[n] and pre[n] = elem[n] }
110
+ pre.name = "sourcecode"
111
+ [r, pre]
112
+ end
113
+
114
+ def source_lex(elem)
115
+ l = (Rouge::Lexer.find(elem["lang"] || "plaintext") ||
116
+ Rouge::Lexer.find("plaintext"))
117
+ l.lex(@c.decode(elem.children.to_xml))
118
+ end
119
+
120
+ def source_label(elem)
121
+ labelled_ancestor(elem) and return
37
122
  lbl = @xrefs.anchor(elem["id"], :label, false) or return
38
123
  prefix_name(elem, block_delim,
39
124
  l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
40
125
  end
41
126
 
42
127
  def formula(docxml)
43
- docxml.xpath(ns("//formula")).each do |f|
44
- formula1(f)
45
- end
128
+ docxml.xpath(ns("//formula")).each { |f| formula1(f) }
46
129
  end
47
130
 
48
131
  def formula1(elem)
@@ -51,48 +134,38 @@ module IsoDoc
51
134
  end
52
135
 
53
136
  def example(docxml)
54
- docxml.xpath(ns("//example")).each do |f|
55
- example1(f)
56
- end
137
+ docxml.xpath(ns("//example")).each { |f| example1(f) }
57
138
  end
58
139
 
59
140
  def example1(elem)
60
141
  n = @xrefs.get[elem["id"]]
61
142
  lbl = if n.nil? || n[:label].nil? || n[:label].empty?
62
143
  @i18n.example
63
- else
64
- l10n("#{@i18n.example} #{n[:label]}")
144
+ else l10n("#{@i18n.example} #{n[:label]}")
65
145
  end
66
146
  prefix_name(elem, block_delim, lbl, "name")
67
147
  end
68
148
 
69
149
  def note(docxml)
70
- docxml.xpath(ns("//note")).each do |f|
71
- note1(f)
72
- end
150
+ docxml.xpath(ns("//note")).each { |f| note1(f) }
73
151
  end
74
152
 
75
153
  def note1(elem)
76
- return if elem.parent.name == "bibitem" || elem["notag"] == "true"
77
-
154
+ elem.parent.name == "bibitem" || elem["notag"] == "true" and return
78
155
  n = @xrefs.get[elem["id"]]
79
156
  lbl = if n.nil? || n[:label].nil? || n[:label].empty?
80
157
  @i18n.note
81
- else
82
- l10n("#{@i18n.note} #{n[:label]}")
158
+ else l10n("#{@i18n.note} #{n[:label]}")
83
159
  end
84
160
  prefix_name(elem, "", lbl, "name")
85
161
  end
86
162
 
87
163
  def admonition(docxml)
88
- docxml.xpath(ns("//admonition")).each do |f|
89
- admonition1(f)
90
- end
164
+ docxml.xpath(ns("//admonition")).each { |f| admonition1(f) }
91
165
  end
92
166
 
93
167
  def admonition1(elem)
94
- return if elem.at(ns("./name")) || elem["notag"] == "true"
95
-
168
+ elem.at(ns("./name")) || elem["notag"] == "true" and return
96
169
  prefix_name(elem, "", @i18n.admonition[elem["type"]]&.upcase, "name")
97
170
  end
98
171
 
@@ -121,15 +194,12 @@ module IsoDoc
121
194
  end
122
195
 
123
196
  def table(docxml)
124
- docxml.xpath(ns("//table")).each do |f|
125
- table1(f)
126
- end
197
+ docxml.xpath(ns("//table")).each { |f| table1(f) }
127
198
  end
128
199
 
129
200
  def table1(elem)
130
- return if labelled_ancestor(elem)
131
- return if elem["unnumbered"] && !elem.at(ns("./name"))
132
-
201
+ labelled_ancestor(elem) and return
202
+ elem["unnumbered"] && !elem.at(ns("./name")) and return
133
203
  n = @xrefs.anchor(elem["id"], :label, false)
134
204
  prefix_name(elem, block_delim, l10n("#{lower2cap @i18n.table} #{n}"),
135
205
  "name")
@@ -137,9 +207,7 @@ module IsoDoc
137
207
 
138
208
  # we use this to eliminate the semantic amend blocks from rendering
139
209
  def amend(docxml)
140
- docxml.xpath(ns("//amend")).each do |f|
141
- amend1(f)
142
- end
210
+ docxml.xpath(ns("//amend")).each { |f| amend1(f) }
143
211
  end
144
212
 
145
213
  def amend1(elem)
@@ -150,9 +218,7 @@ module IsoDoc
150
218
  end
151
219
 
152
220
  def ol(docxml)
153
- docxml.xpath(ns("//ol")).each do |f|
154
- ol1(f)
155
- end
221
+ docxml.xpath(ns("//ol")).each { |f| ol1(f) }
156
222
  @xrefs.list_anchor_names(docxml.xpath(ns(@xrefs.sections_xpath)))
157
223
  end
158
224
 
@@ -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
@@ -1,17 +1,19 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def concept(docxml)
4
+ @definition_ids = docxml.xpath(ns("//definitions//dt"))
5
+ .each_with_object({}) { |x, m| m[x["id"]] = true }
4
6
  docxml.xpath(ns("//concept")).each { |f| concept1(f) }
5
7
  end
6
8
 
7
9
  def concept1(node)
8
10
  xref = node&.at(ns("./xref/@target"))&.text or
9
- return concept_render(node, ital: "true", ref: "true",
11
+ return concept_render(node, ital: "true", ref: "true", bold: "false",
10
12
  linkref: "true", linkmention: "false")
11
- if node.at(ns("//definitions//dt[@id = '#{xref}']"))
12
- concept_render(node, ital: "false", ref: "false",
13
+ if @definition_ids[xref]
14
+ concept_render(node, ital: "false", ref: "false", bold: "false",
13
15
  linkref: "true", linkmention: "false")
14
- else concept_render(node, ital: "true", ref: "true",
16
+ else concept_render(node, ital: "true", ref: "true", bold: "false",
15
17
  linkref: "true", linkmention: "false")
16
18
  end
17
19
  end
@@ -20,21 +22,23 @@ module IsoDoc
20
22
  opts, render, ref = concept_render_init(node, defaults)
21
23
  node&.at(ns("./refterm"))&.remove
22
24
  ref && opts[:ref] != "false" and render&.next = " "
23
- opts[:ital] == "true" and render&.name = "em"
24
25
  concept1_linkmention(ref, render, opts)
25
26
  concept1_ref(node, ref, opts)
26
- concept1_nonital(node, opts)
27
+ concept1_style(node, opts)
27
28
  node.replace(node.children)
28
29
  end
29
30
 
30
- def concept1_nonital(node, opts)
31
- opts[:ital] == "false" or return
32
- r = node.at(ns(".//renderterm"))
33
- r&.replace(r&.children)
31
+ def concept1_style(node, opts)
32
+ r = node.at(ns(".//renderterm")) or return
33
+ opts[:ital] == "true" and r.children = "<em>#{to_xml(r.children)}</em>"
34
+ opts[:bold] == "true" and
35
+ r.children = "<strong>#{to_xml(r.children)}</strong>"
36
+ r.replace(r.children)
34
37
  end
35
38
 
36
39
  def concept_render_init(node, defaults)
37
- opts = %i(ital ref linkref linkmention).each_with_object({}) do |x, m|
40
+ opts = %i(bold ital ref linkref linkmention)
41
+ .each_with_object({}) do |x, m|
38
42
  m[x] = node[x.to_s] || defaults[x]
39
43
  end
40
44
  [opts, node.at(ns("./renderterm")),
@@ -42,7 +46,8 @@ module IsoDoc
42
46
  end
43
47
 
44
48
  def concept1_linkmention(ref, renderterm, opts)
45
- return unless opts[:linkmention] == "true" && !renderterm.nil? && !ref.nil?
49
+ return unless opts[:linkmention] == "true" &&
50
+ !renderterm.nil? && !ref.nil?
46
51
 
47
52
  ref2 = ref.clone
48
53
  r2 = renderterm.clone
@@ -38,15 +38,18 @@ module IsoDoc
38
38
  def anchor_xref(node, target)
39
39
  x = @xrefs.anchor(target, :xref)
40
40
  t = @xrefs.anchor(target, :title)
41
- case node["style"]
42
- when "basic" then t || x
43
- when "full" then t ? anchor_xref_full(x, t) : x
44
- when "short", nil then x
45
- else @xrefs.anchor(target, node[:style].to_sym)
46
- end
41
+ ret = case node["style"]
42
+ when "basic" then t
43
+ when "full" then anchor_xref_full(x, t)
44
+ when "short", nil then x
45
+ else @xrefs.anchor(target, node[:style].to_sym)
46
+ end
47
+ ret || x
47
48
  end
48
49
 
49
50
  def anchor_xref_full(num, title)
51
+ (!title.nil? && !title.empty?) or return nil
52
+
50
53
  l10n("#{num}, #{title}")
51
54
  end
52
55
 
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "2.4.0".freeze
2
+ VERSION = "2.4.1".freeze
3
3
  end
@@ -52,11 +52,17 @@ module IsoDoc
52
52
  @wordstylesheet.unlink if @wordstylesheet.is_a?(Tempfile)
53
53
  end
54
54
 
55
+ def sourcecode_style
56
+ "Sourcecode"
57
+ end
58
+
55
59
  def wordstylesheet_update
56
60
  return if @wordstylesheet.nil?
57
61
 
58
62
  f = File.open(@wordstylesheet.path, "a")
59
63
  @landscapestyle.empty? or f.write(@landscapestyle)
64
+ s = @meta.get[:code_css] and
65
+ f.write(s.gsub(/sourcecode/, "p.#{sourcecode_style}"))
60
66
  if @wordstylesheet_override && @wordstylesheet
61
67
  f.write(@wordstylesheet_override.read)
62
68
  @wordstylesheet_override.close
@@ -70,13 +76,15 @@ module IsoDoc
70
76
  def word_admonition_images(docxml)
71
77
  docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
72
78
  i["width"], i["height"] =
73
- Html2Doc.new({}).image_resize(i, image_localfile(i), @maxheight, 300)
79
+ Html2Doc.new({}).image_resize(i, image_localfile(i), @maxheight,
80
+ 300)
74
81
  end
75
82
  end
76
83
 
77
84
  def word_cleanup(docxml)
78
85
  word_annex_cleanup(docxml)
79
86
  word_preface(docxml)
87
+ word_sourcecode_table(docxml)
80
88
  word_nested_tables(docxml)
81
89
  word_colgroup(docxml)
82
90
  word_table_align(docxml)
@@ -93,6 +101,27 @@ module IsoDoc
93
101
  docxml
94
102
  end
95
103
 
104
+ def word_sourcecode_table(docxml)
105
+ docxml.xpath("//p[@class='Sourcecode']/div[@class='table_container']")
106
+ .each do |d|
107
+ pre = d.at(".//p[@class='Sourcecode']")
108
+ to_sourcecode_para(pre)
109
+ d["id"] = d.parent["id"]
110
+ d.parent.replace(d)
111
+ end
112
+ end
113
+
114
+ def to_sourcecode_para(pre)
115
+ @sourcecode = true
116
+ pre.traverse do |x|
117
+ x.text? or next
118
+ ret = []
119
+ text_parse(x, ret)
120
+ x.replace(ret.join)
121
+ end
122
+ @sourcecode = false
123
+ end
124
+
96
125
  def word_tab_clean(docxml)
97
126
  docxml.xpath("//p[@class='Biblio']//span[@style='mso-tab-count:1']")
98
127
  .each do |s|
@@ -155,7 +184,7 @@ module IsoDoc
155
184
  .each do |t|
156
185
  if t&.previous_element&.name == "img"
157
186
  img = t.previous_element
158
- t.previous_element.swap("<p class=\'figure\'>#{img.to_xml}</p>")
187
+ t.previous_element.swap("<p class='figure'>#{img.to_xml}</p>")
159
188
  end
160
189
  style_update(t&.previous_element, "page-break-after:avoid;")
161
190
  end
@@ -231,7 +260,7 @@ module IsoDoc
231
260
  docxml.xpath("//a[@epub:type = 'footnote']").each do |x|
232
261
  footnote_reference_format(x)
233
262
  end
234
- docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
263
+ docxml.xpath("//a[@class = 'TableFootnoteRef'] | " \
235
264
  "//span[@class = 'TableFootnoteRef']").each do |x|
236
265
  table_footnote_reference_format(x)
237
266
  end
@@ -15,39 +15,50 @@ module IsoDoc
15
15
  table.at(".//tr").xpath("./td | ./th").each do |td|
16
16
  cols += (td["colspan"] ? td["colspan"].to_i : 1)
17
17
  end
18
- style = "border-top:0pt;mso-border-top-alt:0pt;"\
18
+ style = "border-top:0pt;mso-border-top-alt:0pt;" \
19
19
  "border-bottom:#{SW1} 1.5pt;mso-border-bottom-alt:#{SW1} 1.5pt;"
20
20
  tfoot.add_child("<tr><td colspan='#{cols}' style='#{style}'/></tr>")
21
21
  tfoot.xpath(".//td").last
22
22
  end
23
23
 
24
- def make_tr_attr(td, row, totalrows, _header)
25
- style = td.name == "th" ? "font-weight:bold;" : ""
26
- rowmax = td["rowspan"] ? row + td["rowspan"].to_i - 1 : row
27
- style += <<~STYLE
24
+ def make_tr_attr(cell, row, totalrows, header, bordered)
25
+ style = cell.name == "th" ? "font-weight:bold;" : ""
26
+ rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
27
+ style += make_tr_attr_style(row, rowmax, totalrows, header, bordered)
28
+ { rowspan: cell["rowspan"], colspan: cell["colspan"],
29
+ valign: cell["valign"], align: cell["align"], style: style }
30
+ end
31
+
32
+ def make_tr_attr_style(row, rowmax, totalrows, header, bordered)
33
+ ret = <<~STYLE.gsub(/\n/, "")
28
34
  border-top:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
29
35
  mso-border-top-alt:#{row.zero? ? "#{SW1} 1.5pt;" : 'none;'}
30
- border-bottom:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
31
- mso-border-bottom-alt:#{SW1} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
36
+ border-bottom:#{SW1} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;
37
+ mso-border-bottom-alt:#{SW1} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;
32
38
  STYLE
33
- { rowspan: td["rowspan"], colspan: td["colspan"], valign: td["valign"],
34
- align: td["align"], style: style.gsub(/\n/, "") }
39
+ bordered or ret = ""
40
+ pb = header || (totalrows <= 10 && rowmax < totalrows) ? "avoid" : "auto"
41
+ "#{ret}page-break-after:#{pb};"
35
42
  end
36
43
 
37
44
  def table_attrs(node)
45
+ c = node["class"]
46
+ bordered = "border-spacing:0;border-width:1px;"
47
+ (%w(modspec).include?(c) || !c) or bordered = nil
38
48
  ret = {
39
49
  summary: node["summary"],
40
50
  width: node["width"],
41
- style: "mso-table-anchor-horizontal:column;mso-table-overlap:never;"\
42
- "border-spacing:0;border-width:1px;#{keep_style(node)}",
51
+ style: "mso-table-anchor-horizontal:column;mso-table-overlap:never;" \
52
+ "#{bordered}#{keep_style(node)}",
43
53
  class: (node.text.length > 4000 ? "MsoISOTableBig" : "MsoISOTable"),
44
54
  }
55
+ bordered or ret.delete(:class)
45
56
  super.merge(attr_code(ret))
46
57
  end
47
58
 
48
- def colgroup(node, t)
59
+ def colgroup(node, table)
49
60
  colgroup = node.at(ns("./colgroup")) or return
50
- t.colgroup do |cg|
61
+ table.colgroup do |cg|
51
62
  colgroup.xpath(ns("./col")).each do |c|
52
63
  cg.col **{ width: c["width"] }
53
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isodoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-05 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciimath
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rouge
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '4.0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '4.0'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: thread_safe
183
197
  requirement: !ruby/object:Gem::Requirement