metanorma-standoc 1.3.17 → 1.3.18

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/.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