metanorma-standoc 1.3.17 → 1.3.18

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +2 -2
  3. data/.github/workflows/ubuntu.yml +1 -1
  4. data/.github/workflows/windows.yml +1 -1
  5. data/lib/asciidoctor/standoc/base.rb +1 -1
  6. data/lib/asciidoctor/standoc/blocks.rb +3 -2
  7. data/lib/asciidoctor/standoc/cleanup.rb +1 -0
  8. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +1 -2
  9. data/lib/asciidoctor/standoc/cleanup_section.rb +36 -0
  10. data/lib/asciidoctor/standoc/converter.rb +0 -1
  11. data/lib/asciidoctor/standoc/isodoc.rng +1 -1
  12. data/lib/asciidoctor/standoc/macros.rb +1 -101
  13. data/lib/asciidoctor/standoc/macros_plantuml.rb +100 -0
  14. data/lib/asciidoctor/standoc/reqt.rb +6 -6
  15. data/lib/asciidoctor/standoc/utils.rb +2 -2
  16. data/lib/asciidoctor/standoc/validate_section.rb +11 -1
  17. data/lib/metanorma/standoc/version.rb +1 -1
  18. data/metanorma-standoc.gemspec +2 -1
  19. data/spec/asciidoctor-standoc/base_spec.rb +2 -2
  20. data/spec/asciidoctor-standoc/blocks_spec.rb +1 -1
  21. data/spec/asciidoctor-standoc/cleanup_spec.rb +98 -2
  22. data/spec/asciidoctor-standoc/inline_spec.rb +1 -1
  23. data/spec/asciidoctor-standoc/macros_spec.rb +60 -0
  24. data/spec/asciidoctor-standoc/refs_spec.rb +1 -1
  25. data/spec/asciidoctor-standoc/validate_spec.rb +14 -0
  26. data/spec/spec_helper.rb +1 -1
  27. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +98 -98
  28. data/spec/vcr_cassettes/isobib_get_123.yml +31 -31
  29. data/spec/vcr_cassettes/isobib_get_123_2001.yml +16 -16
  30. data/spec/vcr_cassettes/isobib_get_124.yml +27 -27
  31. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  32. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +36 -36
  33. metadata +19 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4647d414467e7326fb0d0d30ee3ac79ad4f3f4a8a2e7d4ffa0948db689781db3
4
- data.tar.gz: ca6d428a27678a89ff8188162046216a7f4f0efe450488d36b158319a91e45a0
3
+ metadata.gz: 29fb2b3bd1b2182033a91de521a848994d54d41592d3c1f850572fd9e4ab6bd5
4
+ data.tar.gz: 1cdecf3c34899fb71b342eafdf16a249e399e35c5382d41fc5965e2870b80988
5
5
  SHA512:
6
- metadata.gz: 97847d11b89413d948324766bda68e416defdb35fd6fed828d6e3bcda8e67fe626a3d14054edce3d580af83c465c786b1a1c11e24585d15054d0cb01d9952bc2
7
- data.tar.gz: 30e844b147945676fa516f98955f878d6b9442c3875f3edcea6ef27a6908a15bc15fedcd26a76619c3068f9f534820db419704abdcb7d2e5562a68dc4a77f9e8
6
+ metadata.gz: 61be98b3231edd09a06711527c2c482cf276fc57bc09eaa10f83316574a9c13aba58b16ab32df29879ffe821d908dc6ad5ea72673328a440da232bd769c8b912
7
+ data.tar.gz: 9f41b2ccbb3e865c7b738a67d00f26c7ddd5230e67af501fc696fb5b80793e933dcd56b08f21e56fab318ad877af77a0c24cce2e454aac85dd1f8d3febc8793a
@@ -29,8 +29,8 @@ jobs:
29
29
  - name: Install LaTeXML
30
30
  run: |
31
31
  # https://github.com/Homebrew/homebrew-core/issues/44950
32
- curl -L https://cpanmin.us | perl - --sudo App::cpanminus
33
- env PATH=$(brew --prefix perl)/bin:$PATH cpanm --sudo --notest LaTeXML@0.8.4
32
+ brew install cpanminus
33
+ cpanm --notest XML::LibXSLT@1.96 LaTeXML@0.8.4
34
34
  - name: Install PlantUML
35
35
  run: |
36
36
  brew install plantuml
@@ -28,7 +28,7 @@ jobs:
28
28
  node-version: '10.x'
29
29
  - name: Update gems
30
30
  run: |
31
- gem install bundler
31
+ gem install bundler
32
32
  bundle install --jobs 4 --retry 3
33
33
  - name: Install LaTeXML
34
34
  run: |
@@ -33,7 +33,7 @@ jobs:
33
33
  - name: Update gems
34
34
  shell: pwsh
35
35
  run: |
36
- gem install bundler
36
+ gem install bundler
37
37
  bundle config --local path vendor/bundle
38
38
  bundle update
39
39
  bundle install --jobs 4 --retry 3
@@ -12,7 +12,7 @@ module Asciidoctor
12
12
  module Standoc
13
13
  module Base
14
14
  XML_ROOT_TAG = "standard-document".freeze
15
- XML_NAMESPACE = "https://www.metanorma.com/ns/standoc".freeze
15
+ XML_NAMESPACE = "https://www.metanorma.org/ns/standoc".freeze
16
16
 
17
17
  Asciidoctor::Extensions.register do
18
18
  inline_macro Asciidoctor::Standoc::AltTermInlineMacro
@@ -206,8 +206,9 @@ module Asciidoctor
206
206
  def quote_attribution(node, out)
207
207
  if node.attr("citetitle")
208
208
  m = /^(?<cite>[^,]+)(,(?<text>.*$))?$/m.match node.attr("citetitle")
209
- out.source m[:text],
210
- **attr_code(target: m[:cite], type: "inline")
209
+ out.source **attr_code(target: m[:cite], type: "inline") do |s|
210
+ s << m[:text]
211
+ end
211
212
  end
212
213
  if node.attr("attribution")
213
214
  out.author { |a| a << node.attr("attribution") }
@@ -43,6 +43,7 @@ module Asciidoctor
43
43
  normref_cleanup(xmldoc)
44
44
  biblio_cleanup(xmldoc)
45
45
  reference_names(xmldoc)
46
+ symbols_cleanup(xmldoc)
46
47
  xref_cleanup(xmldoc)
47
48
  origin_cleanup(xmldoc)
48
49
  concept_cleanup(xmldoc)
@@ -51,8 +51,7 @@ module Asciidoctor
51
51
 
52
52
  def boilerplate_isodoc(xmldoc)
53
53
  x = xmldoc.dup
54
- # TODO variable
55
- x.root.add_namespace(nil, "http://riboseinc.com/isoxml")
54
+ x.root.add_namespace(nil, self.class::XML_NAMESPACE)
56
55
  xml = Nokogiri::XML(x.to_xml)
57
56
  conv = html_converter(EmptyAttr.new)
58
57
  @lang = xmldoc&.at("//bibdata/language")&.text
@@ -4,6 +4,7 @@ require "htmlentities"
4
4
  require "json"
5
5
  require "pathname"
6
6
  require "open-uri"
7
+ require "mathml2asciimath"
7
8
 
8
9
  module Asciidoctor
9
10
  module Standoc
@@ -190,6 +191,41 @@ module Asciidoctor
190
191
  term_children_cleanup(xmldoc)
191
192
  termdocsource_cleanup(xmldoc)
192
193
  end
194
+
195
+ # Indices sort after letter but before any following
196
+ # letter (x, x_m, x_1, xa); we use colon to force that sort order.
197
+ # Numbers sort *after* letters; we use thorn to force that sort order.
198
+ def symbol_key(x)
199
+ key = x.dup
200
+ key.xpath("//*[local-name() = 'math']").each do |m|
201
+ m.replace(MathML2AsciiMath.m2a(m.to_xml))
202
+ end
203
+ ret = Nokogiri::XML(MathML2AsciiMath.m2a(key.to_xml))
204
+ HTMLEntities.new.decode(ret.text).strip.
205
+ gsub(/[[:punct]]|[_^]/, ":\\0").gsub(/`/, "").
206
+ gsub(/[0-9]+/, "þ\\0")
207
+ end
208
+
209
+ def extract_symbols_list(dl)
210
+ dl_out = []
211
+ dl.xpath("./dt | ./dd").each do |dtd|
212
+ if dtd.name == "dt"
213
+ dl_out << { dt: dtd.remove, key: symbol_key(dtd) }
214
+ else
215
+ dl_out.last[:dd] = dtd.remove
216
+ end
217
+ end
218
+ dl_out
219
+ end
220
+
221
+ def symbols_cleanup(docxml)
222
+ docxml.xpath("//definitions/dl").each do |dl|
223
+ dl_out = extract_symbols_list(dl)
224
+ dl_out.sort! { |a, b| a[:key] <=> b[:key] }
225
+ dl.children = dl_out.map { |d| d[:dt].to_s + d[:dd].to_s }.join("\n")
226
+ end
227
+ docxml
228
+ end
193
229
  end
194
230
  end
195
231
  end
@@ -52,7 +52,6 @@ module Asciidoctor
52
52
  end
53
53
 
54
54
  def self.inherited( k )
55
- #k._file = caller.first[/^[^:]+/]
56
55
  k._file = caller_locations.first.absolute_path
57
56
  end
58
57
 
@@ -17,7 +17,7 @@
17
17
  these elements; we just want one namespace for any child grammars
18
18
  of this.
19
19
  -->
20
- <grammar ns="https://www.metanorma.com/ns/standoc" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
20
+ <grammar ns="https://www.metanorma.org/ns/standoc" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
21
21
  <include href="reqt.rng"/>
22
22
  <!-- include "biblio.rnc" { } -->
23
23
  <include href="basicdoc.rng">
@@ -1,6 +1,7 @@
1
1
  require "asciidoctor/extensions"
2
2
  require "fileutils"
3
3
  require "uuidtools"
4
+ require_relative "./macros_plantuml.rb"
4
5
 
5
6
  module Asciidoctor
6
7
  module Standoc
@@ -156,106 +157,5 @@ module Asciidoctor
156
157
  end
157
158
  end
158
159
  end
159
-
160
- class PlantUMLBlockMacroBackend
161
- # https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
162
- def self.plantuml_installed?
163
- cmd = "plantuml"
164
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
165
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
166
- exts.each do |ext|
167
- exe = File.join(path, "#{cmd}#{ext}")
168
- return exe if File.executable?(exe) && !File.directory?(exe)
169
- end
170
- end
171
- nil
172
- end
173
-
174
- def self.run umlfile, outfile
175
- system "plantuml #{umlfile.path}" or (warn $? and return false)
176
- i = 0
177
- until !Gem.win_platform? || File.exist?(outfile) || i == 15
178
- sleep(1)
179
- i += 1
180
- end
181
- File.exist?(outfile)
182
- end
183
-
184
- # if no :imagesdir: leave image file in plantuml
185
- # sleep need for windows because dot works in separate process and
186
- # plantuml process may finish earlier then dot, as result png file
187
- # maybe not created yet after plantuml finish
188
- def self.generate_file parent, reader
189
- localdir = Utils::localdir(parent.document)
190
-
191
- imagesdir = parent.document.attr('imagesdir')
192
- umlfile, outfile = save_plantuml parent, reader, localdir
193
-
194
- # TODO: this should raise failure if there is no image output!!
195
- run(umlfile, outfile) or return
196
- umlfile.unlink
197
-
198
- path = Pathname.new(localdir) + (imagesdir || "plantuml")
199
- path.mkpath
200
-
201
- # TODO: this should raise failure if the destination path already exists!
202
- File.exist?(path) or return
203
-
204
- # TODO: this should raise failure if the destination path is not writable!
205
- File.writable?(path) or return
206
-
207
- # Warning for Heisenbug: metanorma/metanorma-standoc#187
208
- # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
209
- # This is why we need to copy and then unlink.
210
- filename = File.basename(outfile.to_s)
211
- FileUtils.cp(outfile, path) && outfile.unlink
212
-
213
- imagesdir ? filename : File.join(path, filename)
214
- end
215
-
216
- def self.save_plantuml parent, reader, localdir
217
- src = reader.source
218
- reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
219
- src = "@startuml\n#{src}\n@enduml\n"
220
- /^@startuml (?<fn>[^\n]+)\n/ =~ src
221
- Tempfile.open(["plantuml", ".pml"], :encoding => "utf-8") do |f|
222
- f.write(src)
223
- [f, File.join(File.dirname(f.path),
224
- (fn || File.basename(f.path, ".pml")) + ".png")]
225
- end
226
- end
227
-
228
- def self.generate_attrs attrs
229
- through_attrs = %w(id align float title role width height alt).
230
- inject({}) do |memo, key|
231
- memo[key] = attrs[key] if attrs.has_key? key
232
- memo
233
- end
234
- end
235
- end
236
-
237
- class PlantUMLBlockMacro < Asciidoctor::Extensions::BlockProcessor
238
- use_dsl
239
- named :plantuml
240
- on_context :literal
241
- parse_content_as :raw
242
-
243
- def abort(parent, reader, attrs, msg)
244
- # TODO: Abort should really raise an error
245
- warn msg
246
- attrs["language"] = "plantuml"
247
- create_listing_block parent, reader.source, attrs.reject { |k, v| k == 1 }
248
- end
249
-
250
- def process(parent, reader, attrs)
251
- PlantUMLBlockMacroBackend.plantuml_installed? or
252
- return abort(parent, reader, attrs, "PlantUML not installed")
253
- filename = PlantUMLBlockMacroBackend.generate_file(parent, reader) or
254
- return abort(parent, reader, attrs, "Failed to process PlantUML")
255
- through_attrs = PlantUMLBlockMacroBackend.generate_attrs attrs
256
- through_attrs["target"] = filename
257
- create_image_block parent, through_attrs
258
- end
259
- end
260
160
  end
261
161
  end
@@ -0,0 +1,100 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ class PlantUMLBlockMacroBackend
4
+ # https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
5
+ def self.plantuml_installed?
6
+ cmd = "plantuml"
7
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
8
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
9
+ exts.each do |ext|
10
+ exe = File.join(path, "#{cmd}#{ext}")
11
+ return exe if File.executable?(exe) && !File.directory?(exe)
12
+ end
13
+ end
14
+ raise "PlantUML not installed"
15
+ nil
16
+ end
17
+
18
+ def self.run umlfile, outfile
19
+ system "plantuml #{umlfile.path}" or (warn $? and return false)
20
+ i = 0
21
+ until !Gem.win_platform? || File.exist?(outfile) || i == 15
22
+ sleep(1)
23
+ i += 1
24
+ end
25
+ File.exist?(outfile)
26
+ end
27
+
28
+ # if no :imagesdir: leave image file in plantuml
29
+ # sleep need for windows because dot works in separate process and
30
+ # plantuml process may finish earlier then dot, as result png file
31
+ # maybe not created yet after plantuml finish
32
+ def self.generate_file parent, reader
33
+ localdir = Utils::localdir(parent.document)
34
+ imagesdir = parent.document.attr('imagesdir')
35
+ umlfile, outfile = save_plantuml parent, reader, localdir
36
+ run(umlfile, outfile) or raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
37
+ umlfile.unlink
38
+
39
+ path = Pathname.new(localdir) + (imagesdir || "plantuml")
40
+ File.writable?(localdir) or raise "Destination path #{path} not writable for PlantUML!"
41
+ path.mkpath
42
+ File.writable?(path) or raise "Destination path #{path} not writable for PlantUML!"
43
+ #File.exist?(path) or raise "Destination path #{path} already exists for PlantUML!"
44
+
45
+ # Warning: metanorma/metanorma-standoc#187
46
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
47
+ # This is why we need to copy and then unlink.
48
+ filename = File.basename(outfile.to_s)
49
+ FileUtils.cp(outfile, path) && outfile.unlink
50
+
51
+ imagesdir ? filename : File.join(path, filename)
52
+ end
53
+
54
+ def self.save_plantuml parent, reader, localdir
55
+ src = reader.source
56
+ reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
57
+ src = "@startuml\n#{src}\n@enduml\n"
58
+ /^@startuml (?<fn>[^\n]+)\n/ =~ src
59
+ Tempfile.open(["plantuml", ".pml"], :encoding => "utf-8") do |f|
60
+ f.write(src)
61
+ [f, File.join(File.dirname(f.path),
62
+ (fn || File.basename(f.path, ".pml")) + ".png")]
63
+ end
64
+ end
65
+
66
+ def self.generate_attrs attrs
67
+ through_attrs = %w(id align float title role width height alt).
68
+ inject({}) do |memo, key|
69
+ memo[key] = attrs[key] if attrs.has_key? key
70
+ memo
71
+ end
72
+ end
73
+ end
74
+
75
+ class PlantUMLBlockMacro < Asciidoctor::Extensions::BlockProcessor
76
+ use_dsl
77
+ named :plantuml
78
+ on_context :literal
79
+ parse_content_as :raw
80
+
81
+ def abort(parent, reader, attrs, msg)
82
+ warn msg
83
+ attrs["language"] = "plantuml"
84
+ create_listing_block parent, reader.source, attrs.reject { |k, v| k == 1 }
85
+ end
86
+
87
+ def process(parent, reader, attrs)
88
+ begin
89
+ PlantUMLBlockMacroBackend.plantuml_installed?
90
+ filename = PlantUMLBlockMacroBackend.generate_file(parent, reader)
91
+ through_attrs = PlantUMLBlockMacroBackend.generate_attrs attrs
92
+ through_attrs["target"] = filename
93
+ create_image_block parent, through_attrs
94
+ rescue StandardError => e
95
+ abort(parent, reader, attrs, e.message)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -29,8 +29,8 @@ module Asciidoctor
29
29
  def requirement_classification(classif, ex)
30
30
  req_classif_parse(classif).each do |r|
31
31
  ex.classification do |c|
32
- c.tag r[0]
33
- c.value r[1]
32
+ c.tag { |t| t << r[0] }
33
+ c.value { |v| v << r[1] }
34
34
  end
35
35
  end
36
36
  end
@@ -51,11 +51,11 @@ module Asciidoctor
51
51
  classif = node.attr("classification")
52
52
  noko do |xml|
53
53
  xml.send obligation, **attr_code(reqt_attributes(node)) do |ex|
54
- ex.title node.title if node.title
55
- ex.label node.attr("label") if node.attr("label")
56
- ex.subject node.attr("subject") if node.attr("subject")
54
+ node.title and ex.title { |t| t << node.title }
55
+ node.attr("label") and ex.label { |l| l << node.attr("label") }
56
+ node.attr("subject") and ex.subject { |s| s << node.attr("subject") }
57
57
  node&.attr("inherit")&.split(/;\s*/)&.each do |i|
58
- ex.inherit i
58
+ ex.inherit { |inh| inh << i }
59
59
  end
60
60
  requirement_classification(classif, ex) if classif
61
61
  wrap_in_para(node, ex)
@@ -77,8 +77,8 @@ module Asciidoctor
77
77
  end
78
78
 
79
79
  def mn_code(code)
80
- code.sub(/^\(/, "[").sub(/\).*$/, "]").sub(/^nofetch\((.+)\)$/, "\\1")
81
- end
80
+ code.sub(/^\(/, "[").sub(/\).*$/, "]").sub(/^nofetch\((.+)\)$/, "\\1")
81
+ end
82
82
 
83
83
  def emend_biblio(xml, code, title, usrlbl)
84
84
  unless xml.at("/bibitem/docidentifier[not(@type = 'DOI')][text()]")
@@ -5,6 +5,7 @@ module Asciidoctor
5
5
  module Validate
6
6
  def section_validate(doc)
7
7
  sourcecode_style(doc.root)
8
+ hanging_para_style(doc.root)
8
9
  asset_style(doc.root)
9
10
  end
10
11
 
@@ -18,7 +19,7 @@ module Asciidoctor
18
19
  end
19
20
  end
20
21
 
21
- def style_warning(node, msg, text)
22
+ def style_warning(node, msg, text = nil)
22
23
  return if @novalid
23
24
  w = "ISO style: WARNING (#{Utils::current_location(node)}): #{msg}"
24
25
  w += ": #{text}" if text
@@ -37,6 +38,15 @@ module Asciidoctor
37
38
  def asset_style(root)
38
39
  asset_title_style(root)
39
40
  end
41
+
42
+ def hanging_para_style(root)
43
+ root.xpath("//clause | //annex | //foreword | //introduction | "\
44
+ "//acknowledgements").each do |c|
45
+ next unless c.at("./clause")
46
+ next if c.elements.select { |n| n.name != "clause" }.empty?
47
+ style_warning(c, "Hanging paragraph in clause")
48
+ end
49
+ end
40
50
  end
41
51
  end
42
52
  end
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module Standoc
3
- VERSION = "1.3.17".freeze
3
+ VERSION = "1.3.18".freeze
4
4
  end
5
5
  end