isodoc 2.4.0 → 2.4.1

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: 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